【问题标题】:RecyclerView ?android:attr/selectableItemBackground does not work on itemsRecyclerView ?android:attr/selectableItemBackground 对项目不起作用
【发布时间】:2015-09-11 06:22:32
【问题描述】:

我有这个 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>

当我单独使用它时,当我单击视图时,selectableItemBackground 会动画。但是当我将它用于 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);

【问题讨论】:

  • 您是否尝试在适配器中的 holderView 上设置 onClick 侦听器?
  • 我做了......但它没有工作
  • 但是您是否在设置了可选择背景的视图上设置了侦听器?
  • 它对我来说很好用(见this sample project)。
  • @Hellboy 是的,我将侦听器设置在具有背景的项目的根元素上(RelativeLayout)

标签: android android-recyclerview


【解决方案1】:

在您的 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>

【讨论】:

  • 原因是 FrameLayout 在低于 23 的 API 级别上支持 foreground 属性。其他视图仅支持从 API 级别 23 开始。
  • 将此与android:clickable="true"结合使用对我有用
  • @Aba 当我将 clickable 设置为 true 时,我没有收到我的 OnClickListener 事件。
【解决方案2】:

我没有将其设置为背景,而是将其设置为前景,它可以工作。希望对您有所帮助。

android:foreground="?attr/selectableItemBackground"

【讨论】:

  • 我认为它不会在低于 23 的 API 上工作。
  • @VarvaraKalinina 有没有办法让它适用于低于 23 的 api 级别?
【解决方案3】:

其他答案中未提及的内容:需要设置 android:clickable="true" 以在视图未附加 OnClickListener 时使动画正常工作。

【讨论】:

  • 我希望我可以投票两次,因为这个答案显然很久以前就帮助了我
【解决方案4】:

我看到了同样的行为。就我而言,这与以下事实有关:当我单击片段中的列表项并直接用另一个片段替换该片段时,动画没有时间显示。删除片段替换后,我就可以看到动画了。

【讨论】:

    【解决方案5】:
    @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"
    

    【讨论】:

      【解决方案6】:

      就我而言,问题是由DividerItemDecoration 引起的。一旦我摆脱它,它就开始工作了。我建议在RecyclerView中的每个项目在xml文件的末尾添加一行,这样更容易自定义,您不会遇到这类问题。

      【讨论】:

        【解决方案7】:

        您想要产生涟漪效果的视图必须是可点击的。您可以通过在 XML 文件中指定 android:clickable="true" 或以编程方式设置 onClickListener 来做到这一点。当您在 RecyclerView 内的项目上使用它并且您在 ViewHolder 类的“itemView”上使用 Kotlin 设置 onClickListener 时。

        【讨论】:

          【解决方案8】:

          以前的解决方案都不适合我。

          最后我不得不为此实现我自己的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 之前版本的实现。请查看this post

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-04-20
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多