RecyclerView?android:attr / selectableItemBackground不适用于项

20

我有这个 items.xml 文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:focusable="true"
android:clickable="true"
android:background="?android:attr/selectableItemBackground"
android:layout_height="wrap_content">

<ImageView
    android:layout_width="match_parent"
    android:layout_height="60dp"
    android:id="@+id/colorPreview" />


<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:textAppearance="@android:style/TextAppearance.Large"
    android:textColor="@android:color/white"
    android:id="@+id/colorName" />

</RelativeLayout>

当我单独使用它时,可选择的项背景会在我点击视图时执行动画。但是当我将其用于RecyclerView中的项时,单击效果不再发生。我该如何解决这个问题?

PS:如果相关的话,这是RecyclerView上的监听器:

 public ColorListOnItemTouchListener(Context context, OnItemClickListener clickListener) {
    mClickListener = clickListener;
    mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
        @Override
        public boolean onDown(MotionEvent e) {
            return true;
        }

        @Override
        public void onLongPress(MotionEvent e) {
                if(childView != null && mClickListener != null) {
                    mClickListener.onItemLongPress(childView, index);
                }
        }

        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            if(childView != null && mClickListener != null) {
                mClickListener.onItemClick(childView, index);
            }
            return true;
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            return false;
        }
    });
}

谢谢!

编辑:

 public class ColorsCursorAdapter extends RecyclerView.Adapter<ColorsCursorAdapter.ViewHolder> {

    private static final int layout = R.layout.color_item;
    private Cursor mCursor;

    public ColorsCursorAdapter(Cursor c) {
        super();
        this.mCursor = c;
    }


    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(layout, parent, false);
        TextView name = (TextView) v.findViewById(R.id.colorName);
        ImageView image = (ImageView) v.findViewById(R.id.colorPreview);
        return new ViewHolder(v, name, image);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        mCursor.moveToPosition(position);
        int color = mCursor.getInt(mCursor.getColumnIndex(ColorItem.COLUMN_COLOR));
        holder.colorName.setText(Utils.getColorString(color));
        holder.colorPreview.setImageDrawable(new ColorDrawable(color));
    }

    @Override
    public int getItemCount() {
        if(mCursor != null) {
            return mCursor.getCount();
        }
        return 0;
    }

    public void swapCursor(Cursor c) {
        mCursor = c;
        notifyDataSetChanged();
    }

    public Cursor getCursor() {
        return mCursor;
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {
        public TextView colorName;
        public ImageView colorPreview;

        public ViewHolder(View root, TextView colorName, ImageView colorPreview) {
            super(root);
            root.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //
                }
            });
            this.colorName = colorName;
            this.colorPreview = colorPreview;
        }
    }
}

适配器是使用以下方式创建的:

colorList.setLayoutManager(new LinearLayoutManager(this));
    adapter = new ColorsCursorAdapter(null);
    colorList.setAdapter(adapter);

@Hellboy 是的,我正在设置侦听器在具有背景(RelativeLayout)的项目的根元素上。 - Matei Suica
请发布代码,展示您如何创建您的Recycler和Adapter。 - Hellboy
另外一件事。请将“?android:attr/selectableItemBackground”替换为“?attr/selectableItemBackground”。 - Hellboy
尝试过了...仍然没有运气。 - Matei Suica
我被同样的问题困扰着。它在其他适配器中甚至可以工作,但在特定的一个上却不行。无法弄清楚是什么原因导致的。如果我设法解决了,会通知你 :) - dimsuz
显示剩余5条评论
8个回答

54

其他答案中没有提到的一点是:在视图未附加 OnClickListener 时,设置 android:clickable="true" 是必需的,以使动画正常工作。


我希望我能点赞两次,因为这个回答显然在很久以前就帮助了我。 - BabyishTank

24

我将其设置为前景而不是背景,这样就有效了。希望有所帮助。

android:foreground="?attr/selectableItemBackground"

7
我认为它在23以下的API上不会起作用。 - Varvara Kalinina
@VarvaraKalinina,有没有办法让它适用于低于23的API级别? - Rat-a-tat-a-tat Ratatouille

10
在你的items.xml文件中,将FrameLayout设置为根布局,并且为FrameLayout设置selectableItemBackground。这对我有效,但我不知道原因。
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:foreground="?android:selectableItemBackground">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <!-- your code -->
    </RelativeLayout>
</FrameLayout>

3
这是因为FrameLayout在低于API 23的级别上支持“foreground”属性,而其他视图从API级别23开始才支持它。 - ubuntudroid
2
结合使用 android:clickable="true" 对我很有帮助。 - Aba
1
@Aba 当我将 clickable 设置为 true 时,我无法接收到 OnClickListener 事件。 - TheRealChx101

2

想要具有涟漪效果的视图必须可点击。您可以通过在XML文件中指定android:clickable="true"或在程序中设置onClickListener来实现。当您在RecyclerView内使用此方法并且使用Kotlin时,请在ViewHolder类上的“itemView”上设置onClick监听器。


0
@Override
    public boolean onSingleTapUp(MotionEvent e) {
        if(childView != null && mClickListener != null) {
            mClickListener.onItemClick(childView, index);
        }
        return true;
    }

返回false可能可以解决这个问题。对于我来说,我在我的按钮上覆盖了onTouch方法,并在结尾处返回true。返回false可以启用触摸动画的设置:

android:background="?attr/selectableItemBackground"

0
在我的情况下,问题是由DividerItemDecoration引起的。一旦我摆脱了它,它就开始工作了。我建议为RecyclerView中的每个项目在xml文件末尾放置一行,这样更容易定制,也不会遇到这些问题。

0

我也遇到了同样的问题。在我的情况下,这是因为当我在片段中点击列表项并直接用另一个片段替换它时,动画没有时间显示。一旦我移除了片段替换,我就能看到动画了。


0

之前的解决方案都对我没用。

最终我不得不自己实现一个drawable,它的工作方式就像Android提供的那样。

  • 创建一个新的drawable:

res/drawable/selectable_item_background.xml

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/colorAccent">
    <item
        android:id="@android:id/mask"
        android:drawable="@android:color/white" />
</ripple>
  • 在你的单元格中使用它:

就像你使用 Android drawable 一样

android:background="@drawable/selectable_item_background"

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/selectable_item_background"
    android:clickable="true"
    android:orientation="vertical">
    ...

如需更多信息或在API 21之前的版本中实现,请查看此帖子


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