【问题标题】:Override Android-L CardView state_pressed for Older versions of Android为旧版本的 Android 覆盖 Android-L CardView state_pressed
【发布时间】:2014-07-01 20:01:44
【问题描述】:

在最新的 Android SDK 中,我们现在有了新的 CardView,我用新版本替换了旧的 CustomCardView,但是在旧版本的 Android 上运行时,我发现 state_pressedstate_focused 是丑陋的方块它显示在 CardView 上方...

有谁知道我如何在新的 CardView 中模拟以下内容,但仅限于使用旧版本的 Android 时?

<selector xmlns:android="http://schemas.android.com/apk/res/android"
    android:enterFadeDuration="150"
    android:exitFadeDuration="150" >

    <item android:state_pressed="true"
          android:drawable="@drawable/card_on_press"/>
    <item android:state_focused="true" android:state_enabled="true"
          android:drawable="@drawable/card_on_focus"/>
    <item android:state_enabled="true"
          android:drawable="@drawable/card_default"/>
    <item android:state_enabled="false"
          android:drawable="@drawable/card_on_press"/>

</selector>

对于那些对这里感兴趣的人来说,我现在正在使用 CardView:

<android.support.v7.widget.CardView
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/CardView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginLeft="10dp"
    android:layout_marginRight="10dp"
    android:layout_marginTop="10dp"
    android:foreground="?android:attr/selectableItemBackground"
    android:onClick="RunSomeMethod"
    card_view:cardCornerRadius="4dp"
    android:focusable="true"
    android:elevation="2dp">

    <LinearLayout
        android:id="@+id/LinearLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:focusable="false"
        android:visibility="visible">

    </LinearLayout>
</android.support.v7.widget.CardView>

【问题讨论】:

  • 快速更新,我已经在 'Values/styles.xml' & 'Values-v21/styles' v21+: &lt;style name="CardViewStyle" parent="CardView.Light"&gt; &lt;/style&gt; & <style name="CardViewStyle" parent="nowCardStyle"> </style>
  • 将替代的可绘制文件添加到“drawable”文件夹中,与“drawable-v21”相比就足够了吗?
  • 新的 CardView 使用自己的背景可绘制对象。
  • 正确。忘记了。所以你不能在 "drawable-v21" 中使用原始的,而在 "drawable" 中使用你自己的吗?
  • 这基本上就是我所做的,您可以在下面的答案中看到。

标签: android android-5.0-lollipop android-cardview


【解决方案1】:

用以下代码修复:

values-v21\styles.xml:

<style name="CardViewStyle" parent="CardView.Light">
    <item name="android:foreground">?android:attr/selectableItemBackground</item>
</style>

值\styles.xml:

<style name="CardViewStyle" parent="android:Widget.TextView">
    <item name="android:foreground">@drawable/card</item>
</style>

来自 layout\main_layout.xml 的卡片:

<android.support.v7.widget.CardView
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/Card_View"
    style="@style/CardViewStyle"
    android:layout_width="480dp"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:layout_marginLeft="10dp"
    android:layout_marginRight="10dp"
    android:layout_marginTop="10dp"
    card_view:cardCornerRadius="4dp"
    android:elevation="2dp">

这将允许您提供 v21+ 中的动画,但也可以提供 v21 之前的替代动画,而不是蓝色/灰色大方块。

这里是 card.xml 我用来作为你感兴趣的人的drawable:

<selector xmlns:android="http://schemas.android.com/apk/res/android"
    android:enterFadeDuration="150"
    android:exitFadeDuration="150" >

    <item android:state_pressed="true"
          android:drawable="@drawable/card_on_press"/>
    <item android:state_focused="true" android:state_enabled="true"
          android:drawable="@drawable/card_on_focus"/>
    <item android:state_enabled="true"
          android:drawable="@drawable/card_default"/>
    <item android:state_enabled="false"
          android:drawable="@drawable/card_on_press"/>
</selector>

注意: Drawable 默认可以作为透明项目,因为 CardView 为所有 android 版本提供了默认背景。

【讨论】:

  • 你在哪里生成资源:@drawable/card_on_press、@drawable/card_default、@drawable/card_on_focus、@drawable/card_on_press 它们是什么样的?
  • 我为每个文件创建了一个 xml 文件,其中包含类似于以下代码的内容
  • 对不起,我无法编辑我的帖子,我在这里创建了另一个帖子,其中包含 card_on_press.xml 文件代码,每个帖子都一样,但每个人的颜色不同,card_default 会是透明的(完全没有颜色),但其他颜色会稍微深一点,您可以在colors.xml文件中创建这些颜色,并根据需要在上面的代码中调整颜色名称。
  • 我可以看到选择器工作的唯一方法是如果我将属性 android:clickable="true" 添加到 CardView 元素。但如果我这样做,它会覆盖我设置的 clicklisteners。如何让点击监听器和选择器同时工作?
  • 将 android:onClick="RunSomeMethod" 添加到 CardView 并从卡片子视图中删除类似的内容。
【解决方案2】:

也许该库已更新,但当我使用以下内容时,它在旧版本的 Android 上看起来不错。

您可以使用 'CardView.Dark' 和 CardView.Light' (将使用卡片支持库自动生成)

在你的 values/styles.xml 中

<style name="CardViewStyle.Light" parent="CardView.Light">
    <item name="android:foreground">?android:attr/selectableItemBackground</item>
</style>

<style name="CardViewStyle.Dark" parent="CardView.Dark">
    <item name="android:foreground">?android:attr/selectableItemBackground</item>
</style>

卡片视图的布局

创建两种布局,一种用于深色,一种用于浅色。它们将包括这样的卡片视图:

<android.support.v7.widget.CardView
        android:id="@+id/my_card_view"
        style="@style/CardViewStyle.Light"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:orientation="vertical"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginBottom="8dp"
        app:cardCornerRadius="2dp"
        android:elevation="2dp">

    ... other layout stuff ...

</android.support.v7.widget.CardView>

<android.support.v7.widget.CardView
        android:id="@+id/my_card_view"
        style="@style/CardViewStyle.Dark"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:orientation="vertical"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginBottom="8dp"
        app:cardCornerRadius="2dp"
        android:elevation="2dp">

    ... other layout stuff ...

</android.support.v7.widget.CardView>

注意在每个 CardView 中切换样式。

其他自定义

如果您想自定义颜色而不仅仅是黑色或白色,您可以使用以下内容:

要获取 CardView 可绘制对象,您可以使用:

View cardView = findViewById(R.id.my_card_view);
Drawable cardViewDrawable cardView.getBackground();
convertIcon(setViewBackground(cardView, cardViewDrawable));

我的“convertIcon”如下:

/**
 *
 * @param drawable e.g. "getResources().getDrawable(R.drawable.my_drawable)"
 * @param tint e.g. "Color.parseColor(lightTitlebarFg)"
 * @return Drawable
 *
 */
public static Drawable convertIcon(Drawable drawable, int tint) {
    ColorFilter filter = new PorterDuffColorFilter(tint, PorterDuff.Mode.SRC_ATOP);
    drawable.setColorFilter(filter);
    return drawable;
}

我的“setViewBackground”如下:

@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@SuppressWarnings("deprecation")
public static void setViewBackground(View view, Drawable drawable){
    if (UIUtils.isJB()) {
        view.setBackground(drawable);
    } else {
        view.setBackgroundDrawable(drawable);
    }
}

StateListDrawable

如果您想以编程方式创建 StateListDrawable 可以使用以下内容:

StateListDrawable states = new StateListDrawable();
states.addState(new int[] { android.R.attr.state_focused }, focusedDrawable);
states.addState(new int[] { android.R.attr.state_activated }, activatedDrawable);
states.addState(new int[] { android.R.attr.state_enabled }, defaultDrawable);
states.addState(new int[] {}, defaultDrawable);

【讨论】:

    【解决方案3】:

    这是我在存储在项目的可绘制文件夹中的 card_on_press.xml 文件中使用的代码:

    <item>
        <shape>
            <padding
                android:bottom="0dp"
                android:left="0dp"
                android:right="0dp"
                android:top="0dp" />
            <solid android:color="@color/transparent" />
        </shape>
    </item>
    
    <item>
        <shape>
            <padding
                android:bottom="0dp"
                android:left="0dp"
                android:right="0dp"
                android:top="0dp" />
            <solid android:color="@color/card_shadow_1_on_press" />
            <corners android:radius="8dp" />
        </shape>
    </item>
    <item>
        <shape>
            <padding
                android:bottom="0dp"
                android:left="0dp"
                android:right="0dp"
                android:top="0dp" />
            <solid android:color="@color/card_shadow_2_on_press" />
            <corners android:radius="8dp" />
        </shape>
    </item>
    <!-- Background -->
    <item>
        <shape>
            <solid android:color="@color/card_background_on_press" />
            <corners android:radius="8dp" />
        </shape>
    </item>
    

    【讨论】:

    • 非常有趣,但是这个可绘制的 XML 有问题,它似乎不完整,请您发布整个文件吗?谢谢!
    • 嗨微笑者,请问您使用背景做什么?谢谢!
    • 我使用 'android.support.v7.widget.CardView' 作为父视图,为其提供默认的 cardview bg,而 alt bg 仅适用于较旧的 android 版本,以使它们在按下时显得更暗,即使在较旧的 android 版本上,其余的仍然由 cardview 完成。您将需要复制此文件并为每个状态重命名它,即:按下/默认/焦点等。这样做的目的是让您将较暗覆盖的角落四舍五入,使其看起来只是卡片视图而不是叠加层。抱歉,如果我解释得不够清楚...
    • 这里的大多数其他帖子也包含创建所需结果所需的代码。
    • 我为混乱道歉。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    • 2013-12-06
    • 2015-12-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多