CardView的背景会根据android:state_selected和android:state_pressed做出响应。

4
我指的是https://dev59.com/I2Af5IYBdhLWcg3wmzpL#24475228中的回答。
该回答使用了Android中的可绘制对象:?android:attr/selectableItemBackground

enter image description here

以下是当我点击卡片时发生的情况。请注意,通过使用来自Android的可绘制对象,android:state_selected="true"(当setSelected(true))将不会产生任何颜色变化效果。
因此,我想使用自己定义的可绘制对象来实现以下目的:
  1. 它看起来更漂亮。
  2. 能够处理android:state_selected="true"
这是我的代码。

statelist_item_background.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_pressed="true" android:drawable="@drawable/selected_background" />
    <item android:state_selected="true" android:drawable="@drawable/selected_background" />
    <item android:drawable="@android:color/transparent" />

</selector>

selected_background.xml

<shape android:shape="rectangle" xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="#ffffe1b3" />
    <stroke
        android:width="1px"
        android:color="#fff76d3c" />
</shape>

card_row.xml

<!-- A CardView that contains a TextView -->
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/card_view"
    android:layout_marginLeft="5dp"
    android:layout_marginRight="5dp"
    android:layout_marginTop="5dp"
    android:layout_marginBottom="5dp"
    android:clickable="true"
    android:foreground="@drawable/statelist_item_background"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:padding="5dp"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView
            android:id="@+id/txt_label_item"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceLarge"
            tools:text="Item Number One" />

        <TextView
            android:id="@+id/txt_date_time"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceMedium"
            tools:text="Item Number One" />
    </LinearLayout>
</android.support.v7.widget.CardView>

当我长按卡片项并执行childView.setSelected(true);时,这是我的结果。

enter image description here

我所有的卡片内容(TextView)都被阻止了。我该如何避免这种情况?
关于使用android:background的一些注意事项
请注意,当您将android:background="@drawable/statelist_item_background"CardView本身一起使用时,不会发生任何事情。
但是,如果您将android:background="@drawable/statelist_item_background"CardViewLinearLayout一起使用,您将得到以下不完美的结果。

enter image description here

突出显示的颜色未覆盖整个卡片

更新

看起来这是CardView的限制 - https://code.google.com/p/android/issues/detail?id=78198 使用“前景”作为解决方法不是一个选项,因为它会覆盖卡片内容。


你在更改时将卡片视图背景设置为什么? - Chad Bingham
6个回答

4

经过一番实验,我可以基本确定这是当前CardView的限制 - https://code.google.com/p/android/issues/detail?id=78198

不要使用CardView的前景变通方法。尽管它被广泛提议,但实际上不起作用!

我的建议是,如果需要自定义选择器,请避免使用CardView。可以使用LayerDrawable替换它。我所做的就是这样。

card.xml

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape>
            <padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
            <solid android:color="@android:color/transparent" />
            <stroke
                android:width="1dp"
                android:color="#ffededed" />
            <corners android:radius="2dp" />
        </shape>
    </item>

    <item>
        <shape>
            <padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
            <stroke
                android:width="1dp"
                android:color="#ffe8e8e8" />
            <corners android:radius="2dp" />
        </shape>
    </item>

    <item>
        <shape>
            <padding android:top="0dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
            <stroke
                android:width="1dp"
                android:color="#ffe1e1e1" />
            <corners android:radius="2dp" />
        </shape>
    </item>

    <item>
        <shape>
            <padding android:top="0dp" android:right="0dp" android:bottom="1dp" android:left="0dp" />
            <stroke
                android:width="1dp"
                android:color="#ffdbdbdb" />
            <corners android:radius="2dp" />
        </shape>
    </item>

    <item>
        <shape>
            <padding android:top="0dp" android:right="0dp" android:bottom="1dp" android:left="0dp" />
            <stroke
                android:width="1dp"
                android:color="#ffd5d5d5" />
            <corners android:radius="2dp" />
        </shape>
    </item>

    <!--
    <item>
        <shape>
            <padding android:top="0dp" android:right="0dp" android:bottom="1dp" android:left="0dp" />
            <stroke
                android:width="1dp"
                android:color="#ffcfcfcf" />
            <corners android:radius="2dp" />
        </shape>
    </item>
    -->

    <item>
        <shape >
            <solid android:color="#ffffffff" />
            <corners android:radius="2dp" />
        </shape>
    </item>
</layer-list>

card_selected.xml

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape>
            <padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
            <stroke
                android:width="1dp"
                android:color="#ffededed" />
            <corners android:radius="2dp" />
        </shape>
    </item>

    <item>
        <shape>
            <padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
            <stroke
                android:width="1dp"
                android:color="#ffe8e8e8" />
            <corners android:radius="2dp" />
        </shape>
    </item>

    <item>
        <shape>
            <padding android:top="0dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
            <stroke
                android:width="1dp"
                android:color="#ffe1e1e1" />
            <corners android:radius="2dp" />
        </shape>
    </item>

    <item>
        <shape>
            <padding android:top="0dp" android:right="0dp" android:bottom="1dp" android:left="0dp" />
            <stroke
                android:width="1dp"
                android:color="#ffdbdbdb" />
            <corners android:radius="2dp" />
        </shape>
    </item>

    <item>
        <shape>
            <padding android:top="0dp" android:right="0dp" android:bottom="1dp" android:left="0dp" />
            <stroke
                android:width="1dp"
                android:color="#ffd5d5d5" />
            <corners android:radius="2dp" />
        </shape>
    </item>

    <!--
    <item>
        <shape>
            <padding android:top="0dp" android:right="0dp" android:bottom="1dp" android:left="0dp" />
            <stroke
                android:width="1dp"
                android:color="#ffcfcfcf" />
            <corners android:radius="2dp" />
        </shape>
    </item>
    -->

    <item>
        <shape>
            <solid android:color="#ffffe1b3" />
            <stroke
                android:width="1px"
                android:color="#fff76d3c" />
            <corners android:radius="2dp" />
        </shape>
    </item>
</layer-list>

statelist_item_background.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
    android:exitFadeDuration="@android:integer/config_mediumAnimTime">

    <item android:state_pressed="true" android:drawable="@drawable/card_selected" />     <!-- pressed -->
    <item android:state_selected="true" android:drawable="@drawable/card_selected" />     <!-- pressed -->

    <item android:drawable="@drawable/card" />

</selector>

layout.xml

<!-- A CardView that contains a TextView -->

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:padding="10dp"
    android:layout_marginLeft="5dp"
    android:layout_marginRight="5dp"
    android:layout_marginTop="5dp"
    android:layout_marginBottom="5dp"
    android:background="@drawable/statelist_item_background"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clickable="true" >

    <TextView
        android:id="@+id/txt_label_item"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        tools:text="Item Number One" />

    <TextView
        android:id="@+id/txt_date_time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium"
        tools:text="Item Number One" />
</LinearLayout>

你将获得非常好的结果。 enter image description here

1
我刚刚尝试了 MaterialCardView,它可以正常工作:

<com.google.android.material.card.MaterialCardView
    android:id="@+id/material_card_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="@dimen/activity_vertical_margin"
    app:cardCornerRadius="4dp"
    app:cardBackgroundColor="@color/selector_background_color"
    app:strokeWidth="2dp">

selector_background_color.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@android:color/white" android:state_activated="true"/>
<item android:color="@android:color/darker_gray" android:state_activated="false"/>

在Activity/Fragment中:
material_card_view.setOnClickListener {
        it.isActivated = !it.isActivated
}

对于strokeColor,您不能使用选择器。如果您希望描边颜色根据选择器状态更改,则必须以编程方式执行此操作。
状态激活的示例:
val colorStateList: ColorStateList = 
ResourcesCompat.getColorStateList(resources, 
R.color.selector_stroke_color, null)!!
val colorForState =colorStateList.getColorForState(intArrayOf(android.R.attr.state_activated), colorStateList.defaultColor)
material_card_view.strokeColor = colorForState

0

如果背景没有覆盖整个卡片的问题,那是由于cornerRadius绘制限制引起的。有两种解决方案:

  1. 禁用卡片的圆角将解决问题。app:cardCornerRadius="0dp"

  2. 您可以保留cardCornerRadius,但需要设置app:cardPreventCornerOverlap="false"


0
我的所有卡片内容(TextViews)都被阻止了。我该如何避免这种情况?
您的阻塞问题可以通过一些颜色理论知识轻松解决。您可以使用具有更高透明度的桃色变体,而不是使用给定的桃色。
Android中的颜色代码方案为xxyyyyyy
xx是您的透明度级别,y是您的颜色。
xx的最大值为:ff //这是完全可见的
xx的最小值为:00 //这是完全不可见的
因此,通过在色轮上玩耍,您可以获得所需视图所需的正确透明度的正确效果。

使用 alpha 值是无法解决问题的。如果您使用非零的 alpha 值,文本视图似乎会被一个“模糊”层所阻挡。如果您使用零 alpha 值(完全透明),则根本没有颜色。 - Cheok Yan Cheng

0

MaterialCardView 具有涟漪效果,不像 CardView 需要自定义背景可绘制。 这处理了我的用例中的 android:state_selectedandroid:state_pressed


-1

我相信你误解了你所提到的问题。这个问题是如何获得水波纹效果:

enter link description here

我认为你只是在寻找点击反馈? 如果是这样,请尝试设置背景可绘制对象:

  android:background="@drawable/statelist_item_background"

编辑:

在你的背景颜色xml中,你需要给它一个alpha值。它被绘制在前面,所以给它一个alpha值为.1f,看看效果如何,然后再进行调整。 尝试使用颜色50F76D3C,然后像最初一样将其用于前景。


使用 android:background 不会有太大帮助。我在关于使用 android:background 的问题中更新了我的发现。 - Cheok Yan Cheng
使用 alpha 值是无法解决问题的。如果您使用非零的 alpha 值,文本视图似乎会被一个“模糊”层所阻挡。如果您使用零 alpha 值(完全透明),则根本没有颜色。 - Cheok Yan Cheng

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接