设置RecyclerView的OnItemClickListener

RecyclerView的出现代替了ListView的“霸主地位”,关于RecyclerView的好处这里不再多说,不过用过RecyclerView的朋友们都知道,这个傲娇的View没有提供setOnItemClickListener方法,如果我们要实现这样的功能该怎么做呢?翻遍了网上所有的实现方式,下面介绍两中我觉得还不错的方法。

通过ViewHolder传入监听接口:

RecyclerView自己提供了ViewHolder,了解的朋友们都知道,在RecyclerView的ViewHolder构造方法中,有这么一个参数:View itemView

class MyViewHolder extends ViewHolder {

            ImageView categoryImage;
            TextView categoryName;

            public MyViewHolder(View itemView, OnItemClickListener onItemClickListener) {
                super(itemView);
                categoryName = (TextView) itemView.findViewById(R.id.category_name);
                categoryImage = (ImageView) itemView.findViewById(R.id.category_image);
                itemView.setOnClickListener(v -> onItemClickListener.OnItemClick(getPosition(), v));
            }
        }

如上述代码是我写的一个例子,ViewHolder的构造方法中,有一个itemView的参数,而这个参数就是RecyclerView中的每个item,而我们要设置点击监听的不就是它么,所以从这里入手,我们可以传一个自定义监听接口给ViewHolder作为构造方法的参数,然后在里面为itemView设置这个监听接口(在onClick中调用我们自己写的接口的方法)

然后再把视线转到RecyclerView的onCreateViewHolder方法中,这个方法是创建ViewHolder的地方,看代码:

 @Override
        public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(mContext).
                    inflate(R.layout.item_horizontal_listview, parent, false);
            return new MyViewHolder(view, onItemClickListener);
        }

从上面的代码可以看到,我们首先从xml中inflate了一个item的view进来,然后将这个view以及一个我们自己写的监听接口实例传给了ViewHolder的构造方法。最终返回了一个ViewHolder实例,这样我们就间接地实现了对item的点击监听。

当然了,这个onItemClickListenr还需要我们提供一个对外的设置接口,这个设置接口可以写在Adapter中,因为我们的ViewHolder就是在Adapter里面的。

下面贴上一个完整的示例代码:

 public class HorizontalListViewAdapter extends Adapter {

        //自定义监听接口
        private OnItemClickListener onItemClickListener;

        @Override
        public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(mContext).
                    inflate(R.layout.item_horizontal_listview, parent, false);
            //从这里将接口实例传给ViewHolder
            return new MyViewHolder(view, onItemClickListener);
        }

        @Override
        public void onBindViewHolder(ViewHolder holder, int position) {
           //代码省略
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public int getItemCount() {
            return mItems.size();
        }

        class MyViewHolder extends ViewHolder {

            ImageView categoryImage;
            TextView categoryName;

            public MyViewHolder(View itemView, OnItemClickListener onItemClickListener) {
                super(itemView);
                categoryName = (TextView) itemView.findViewById(R.id.category_name);
                categoryImage = (ImageView) itemView.findViewById(R.id.category_image);
                itemView.setOnClickListener(v -> onItemClickListener.OnItemClick(getPosition(), v));
            }
        }

        //向外提供设置监听接口
        public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
            this.onItemClickListener = onItemClickListener;
        }
    }
    /**
     * item点击事件监听接口
     */
    interface OnItemClickListener {
        void OnItemClick(int position, View view);
    }

这个实现方式看起来还是比较“优雅的”,网上不少人都是用这个方法,我觉得也挺不错,就mark一下;

接下来再说一个我觉得也比较巧妙的方式,这个方式是我的一个好基友启发了我:重写addView方法:

重写addView方法:

众所周知,一个ViewGroup是通过addView方法来添加自己的子view的,那么RecyclerView也不例外,我们可以在addView方法中,对传进来的每一个child设置点击监听.

addView方法有很多个,经过测试,下面这个方法总是会被调用

@Override
    public void addView(View child, int index, ViewGroup.LayoutParams params) {
        super.addView(child, index, params);
    }

于是我们就拿它“开刀”

这么一来问题就很简单了,这个child参数就是我们要设置监听的对象,对他设置OnClickListener,然后在OnClick方法里面调用我们自己写的接口方法,问题就搞定了。

虽然这个方法我觉得很巧妙(觉得巧妙是因为当我第一次看到这种写法时,不由得惊讶:这样也行?!),但是又隐隐约约觉得这样做不太“友好”,才学疏浅,希望各路大神前来指点一二。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值