Android Lollipop CardView 上的波纹效果

问题描述 投票:0回答:15

我试图通过在活动 XML 文件中设置 android:backgound 属性来让 CardView 在触摸时显示波纹效果,如 Android 开发人员页面上的here所述,但它不起作用。根本没有动画,但是调用了onClick中的方法。我还尝试按照建议创建ripple.xml 文件here,但结果相同。

CardView 显示在活动的 XML 文件中:

<android.support.v7.widget.CardView
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="155dp"
    android:layout_height="230dp"
    android:elevation="4dp"
    android:translationZ="5dp"
    android:clickable="true"
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:onClick="showNotices"
    android:background="?android:attr/selectableItemBackground"
    android:id="@+id/notices_card"
    card_view:cardCornerRadius="2dp">

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

我对 Android 开发比较陌生,所以我可能犯了一些明显的错误。

android android-layout android-5.0-lollipop android-cardview
15个回答
744
投票

您应该将以下内容添加到

CardView

android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"

32
投票

我设法通过以下方式在卡片视图上获得连锁反应:

<android.support.v7.widget.CardView 
    xmlns:card_view="http://schemas.android.com/apk/res-auto" 
    android:clickable="true" 
    android:foreground="@drawable/custom_bg"/>

对于您在上面代码中看到的custom_bg,您必须为lollipop(在drawable-v21包中)和pre-lollipop(在drawable包中)设备定义一个xml文件。 对于drawable-v21包中的custom_bg,代码是:

<ripple 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="?android:attr/colorControlHighlight">
<item
    android:id="@android:id/mask"
    android:drawable="@android:color/white"/>
</ripple>

对于drawable包中的custom_bg,代码为:

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

<item android:state_pressed="true">
    <shape>
        <solid android:color="@color/colorHighlight"></solid>
    </shape>
</item>
<item>
    <shape>
        <solid android:color="@color/navigation_drawer_background"></solid>
    </shape>
</item>
</selector>

因此,在棒棒糖之前的设备上,您将获得稳定的点击效果,而在棒棒糖设备上,您将在卡片视图上产生连锁反应。


15
投票

您正在使用的 appcompat 支持库中省略了连锁反应。如果您想查看波纹,请使用 Android L 版本并在 Android L 设备上进行测试。根据 AppCompat v7 网站:

“为什么预制棒棒糖上没有波纹? 让 RippleDrawable 能够流畅运行的很多因素就是 Android 5.0 新增的 RenderThread。为了优化以前版本的 Android 的性能,我们暂时将 RippleDrawable 排除在外。”

查看此链接此处了解更多信息


15
投票

如果您正在使用的应用程序

minSdkVersion
是9级,您可以使用:

android:foreground="?selectableItemBackground"
android:clickable="true"

相反,从第 11 级开始,您可以使用:

android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"

来自文档:

clickable - 定义此视图是否对单击事件做出反应。必须是布尔值,“true”或“false”。

foreground - 定义在内容上绘制的可绘制对象。这可以用作叠加层。如果重力设置为填充,则前景可绘制对象会参与内容的填充。


13
投票

改用Material Cardview,它扩展了Cardview并提供了多种新功能,包括默认的可点击效果:

<com.google.android.material.card.MaterialCardView>

...

</com.google.android.material.card.MaterialCardView>

依赖关系(最多可使用 API 14 以支持旧设备):

implementation 'com.google.android.material:material:1.0.0'

7
投票

对我来说,将

foreground
添加到
CardView
不起作用(原因未知:/)

将相同的内容添加到其子布局中就可以了。

代码:

<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/card_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:focusable="true"
    android:clickable="true"
    card_view:cardCornerRadius="@dimen/card_corner_radius"
    card_view:cardUseCompatPadding="true">

    <LinearLayout
        android:id="@+id/card_item"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:foreground="?android:attr/selectableItemBackground"
        android:padding="@dimen/card_padding">

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

7
投票

添加这两行类似的代码就像按钮、线性布局或 CardView 等任何视图的魅力一样,只需放置这两行即可看到魔力...

android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"

3
投票

将以下内容添加到您的 xml 中:

android:clickable="true"
android:focusable="true"
android:background="?android:attr/selectableItemBackground"

并添加到您的适配器(如果是您的情况)

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            val attrs = intArrayOf(R.attr.selectableItemBackground)
            val typedArray = holder.itemView.context.obtainStyledAttributes(attrs)
            val selectableItemBackground = typedArray.getResourceId(0, 0)
            typedArray.recycle()

            holder.itemView.isClickable = true
            holder.itemView.isFocusable = true
            holder.itemView.foreground = holder.itemView.context.getDrawable(selectableItemBackground)
        }
    }

2
投票

如果有像RelativeLayout或LinearLayout这样的根布局包含CardView中所有适配器项目的组件,则必须在该根布局中设置背景属性。喜欢:

<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="122dp"
android:layout_marginBottom="6dp"
android:layout_marginLeft="6dp"
android:layout_marginRight="6dp"
card_view:cardCornerRadius="4dp">

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/touch_bg"/>
</android.support.v7.widget.CardView>

2
投票

对于那些寻找解决方案以解决在 RecyclerView 中显示的以编程方式创建的 CardView(或者在我的情况下扩展 CardView 的自定义视图)上不起作用的连锁反应问题的人,以下内容对我有用。基本上,在 XML 布局文件中以声明方式声明其他答案中提到的 XML 属性似乎不适用于以编程方式创建的 CardView,或者从自定义布局创建的 CardView(即使根视图是 CardView 或使用合并元素),因此它们必须像这样以编程方式设置:

private class MadeUpCardViewHolder extends RecyclerView.ViewHolder {
    private MadeUpCardView cardView;

    public MadeUpCardViewHolder(View v){
        super(v);

        this.cardView = (MadeUpCardView)v;

        // Declaring in XML Layout doesn't seem to work in RecyclerViews
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            int[] attrs = new int[]{R.attr.selectableItemBackground};
            TypedArray typedArray = context.obtainStyledAttributes(attrs);
            int selectableItemBackground = typedArray.getResourceId(0, 0);
            typedArray.recycle();

            this.cardView.setForeground(context.getDrawable(selectableItemBackground));
            this.cardView.setClickable(true);
        }
    }
}

哪里

MadeupCardView extends CardView
感谢这个答案
TypedArray
部分。


2
投票
Android

Cardview控制的

Ripple
事件:

<android.support.v7.widget.CardView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:foreground="?android:attr/selectableItemBackground"
    android:clickable="true"
    android:layout_marginBottom="4dp"
    android:layout_marginTop="4dp" />

1
投票
  android:foreground="?android:attr/selectableItemBackgroundBorderless"
   android:clickable="true"
   android:focusable="true"

仅工作 api 21 并使用此功能,而不使用此列表行卡视图


1
投票

我对 AppCompat 不满意,所以我编写了自己的 CardView 和反向移植的 Ripples。这里它在 Galaxy S with Gingerbread 上运行,所以这绝对是可能的。

Demo of Ripple on Galaxy S

有关更多详细信息,请检查源代码


0
投票

如果您想要在卡片视图(子级)内有任何元素,您可以使用:

<ImageView
android:background="?android:attr/selectableItemBackground"

但是如果您需要整个卡片视图,请这样做:

android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"

如果同时使用的话,颜色会比其他的深。

但是,最简单的方法是

com.google.android.material.card.MaterialCardView

0
投票
android:clickable="true"
android:focusable="true"
android:foreground="?android:attr/selectableItemBackground"

为CardView添加上面的涟漪效果代码

© www.soinside.com 2019 - 2024. All rights reserved.