RecyclerView详细介绍-----解决点击事件,刷新错误(二)

RecyclerView基本使用可参考:RecyclerView详细介绍(一)

  1. 前言

RecyclerView 没有提供类似ListView的setOnItemClickListener方法,所以只有我们自己为RecyclerView添加点击事件, 本篇文章主要介绍如何添加点击事件,进行Item增加和删除,并且解决RecycleView Adapter使用notifyItemRemoved和notifyItemInserted造成Position混乱的问题。

2.添加点击事件

1)在Adapter中创建一个实现点击接口:

public interface OnItemClickLitener {
        void onItemClick(View view, int position);
    }

2)在Adapter中添加接口设置方法:

private OnItemClickLitener mOnItemClickListener = null;

    public void setOnItemClickListener(OnItemClickLitener listener) {
        this.mOnItemClickListener = listener;
    }

3)触发itemClick回调代码:

@Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.mTextView.setText(data.get(position));
        holder.mTextView.setTag(holder.getLayoutPosition());
        holder.mTextView.setOnClickListener(this);
    }
@Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.item_text:
                mOnItemClickListener.onItemClick(v, (int) v.getTag());
                break;
        }
    }

4)activity中注册接口到Adapter中:

public class ItemClickListViewActivity extends AppCompatActivity {

    /**
     * view
     */
    private RecyclerView recyclerView;

    /**
     * 用来确定每一个item如何进行排列摆放,何时展示和隐藏
     */
    private LinearLayoutManager layoutManager;

    /**
     * 适配器
     */
    private MyItemClickAdapter mAdapter;

    private ArrayList<String> data = new ArrayList<String>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();
        initData();
    }

    /**
     * 初始化布局组件
     */
    private void initView() {
        recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        //创建默认的线性LayoutManager
        layoutManager = new LinearLayoutManager(this);
//        layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
        recyclerView.setLayoutManager(layoutManager);
        //如果可以确定每个item的高度是固定的,设置这个选项可以提高性能
        recyclerView.setHasFixedSize(true);
    }

    /**
     * 初始化数据
     */
    private void initData() {
        for (int i = 0; i < 100; i++) {
            data.add(i + "--->click");
        }
        //创建并设置Adapter
        mAdapter = new MyItemClickAdapter(data);
        recyclerView.setAdapter(mAdapter);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        mAdapter.setOnItemClickListener(new MyItemClickAdapter.OnItemClickLitener() {
            @Override
            public void onItemClick(View view, int position) {
                if(position ==2){
                    mAdapter.addItem("add click", 4);
                    Toast.makeText(ItemClickListViewActivity.this, "增加数据" + position, Toast.LENGTH_SHORT).show();
                }else if(position ==3) {
                    mAdapter.removeItem(2);
                    Toast.makeText(ItemClickListViewActivity.this, "删除数据" + position, Toast.LENGTH_SHORT).show();
                }else{

                    Toast.makeText(ItemClickListViewActivity.this, "选中" + position, Toast.LENGTH_SHORT).show();
                }
            }
        });
    }
}

以上代码就可以为RecyclerView添加item点击事件了。

3.Item增加和删除

在adpater中增加如下两个方法:
1)添加数据:

public void addItem(String content, int position) {
        data.add(position, content);
        notifyItemInserted(position);
    }

2)删除数据:

public void removeItem(int position) {
        data.remove(position);
        notifyItemRemoved(position);
    }

activity中调用上面两个方法,实现增加跟删除item

mAdapter.setOnItemClickListener(new MyItemClickAdapter.OnItemClickLitener() {
            @Override
            public void onItemClick(View view, int position) {
                if(position ==2){
                    mAdapter.addItem("add click", 4);
                    Toast.makeText(ItemClickListViewActivity.this, "增加数据" + position, Toast.LENGTH_SHORT).show();
                }else if(position ==3) {
                    mAdapter.removeItem(2);
                    Toast.makeText(ItemClickListViewActivity.this, "删除数据" + position, Toast.LENGTH_SHORT).show();
                }else{

                    Toast.makeText(ItemClickListViewActivity.this, "选中" + position, Toast.LENGTH_SHORT).show();
                }
            }
        });

4.解决增加或者删除position混乱的问题:

照Google文档描述在使用了notifyItemInserted时候原来位置的position会加1,但是事实证明数据的position位置毫无变化,暂且认为google工程师的错误吧,但是我们还是要继续使用。一般有两种解决办法:
1)保留删除跟添加动画效果:notifyItemRemoved(position);notifyItemInserted(position);从源码可以看出,他只是刷新当前插入或者删除的item,不会触发onBindViewHolder,所以插入或者删除的item的下方的item的postion会有混乱。所以我们手动来刷新,代码如下:

public void removeItem(int position) {
        data.remove(position);
        notifyItemRemoved(position);
        // 加入如下代码保证position的位置正确性
        if (position != data.size() - 1) {
            notifyItemRangeChanged(position, data.size() - position);
        }
    }

    public void addItem(String content, int position) {
        data.add(position, content);
        notifyItemInserted(position);
        // 加入如下代码保证position的位置正确性
        if (position != data.size() - 1) {
            notifyItemRangeChanged(position, data.size() - position);
        }
    }

2)去掉动画:直接使用notifyDataSetChanged();因为使用notifyDataSetChanged();后,动画则消失了。

public void removeItem(int position) {
        data.remove(position);
        notifyItemRemoved(position);
        notifyDataSetChanged();
    }

    public void addItem(String content, int position) {
        data.add(position, content);
        notifyItemInserted(position);
        notifyDataSetChanged();
    }

5.完整代码

activity代码:

package com.test.recyclerview.itemclick;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.Toast;

import com.test.recyclerview.R;

import java.util.ArrayList;

public class ItemClickListViewActivity extends AppCompatActivity {

    /**
     * view
     */
    private RecyclerView recyclerView;

    /**
     * 用来确定每一个item如何进行排列摆放,何时展示和隐藏
     */
    private LinearLayoutManager layoutManager;

    /**
     * 适配器
     */
    private MyItemClickAdapter mAdapter;

    private ArrayList<String> data = new ArrayList<String>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();
        initData();
    }

    /**
     * 初始化布局组件
     */
    private void initView() {
        recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        //创建默认的线性LayoutManager
        layoutManager = new LinearLayoutManager(this);
//        layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
        recyclerView.setLayoutManager(layoutManager);
        //如果可以确定每个item的高度是固定的,设置这个选项可以提高性能
        recyclerView.setHasFixedSize(true);
    }

    /**
     * 初始化数据
     */
    private void initData() {
        for (int i = 0; i < 100; i++) {
            data.add(i + "--->click");
        }
        //创建并设置Adapter
        mAdapter = new MyItemClickAdapter(data);
        recyclerView.setAdapter(mAdapter);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        mAdapter.setOnItemClickListener(new MyItemClickAdapter.OnItemClickLitener() {
            @Override
            public void onItemClick(View view, int position) {
                if(position ==2){
                    mAdapter.addItem("add click", 4);
                    Toast.makeText(ItemClickListViewActivity.this, "增加数据" + position, Toast.LENGTH_SHORT).show();
                }else if(position ==3) {
                    mAdapter.removeItem(2);
                    Toast.makeText(ItemClickListViewActivity.this, "删除数据" + position, Toast.LENGTH_SHORT).show();
                }else{

                    Toast.makeText(ItemClickListViewActivity.this, "选中" + position, Toast.LENGTH_SHORT).show();
                }
            }
        });
    }
}

adapter代码:

package com.test.recyclerview.itemclick;

import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.test.recyclerview.R;

import java.util.ArrayList;


public class MyItemClickAdapter extends RecyclerView.Adapter<MyItemClickAdapter.ViewHolder> implements View.OnClickListener {
    private OnItemClickLitener mOnItemClickListener = null;

    public void setOnItemClickListener(OnItemClickLitener listener) {
        this.mOnItemClickListener = listener;
    }

    private ArrayList<String> data;

    public MyItemClickAdapter(ArrayList<String> data) {
        this.data = data;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.activity_item, viewGroup, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.mTextView.setText(data.get(position));
        holder.mTextView.setTag(holder.getLayoutPosition());
        holder.mTextView.setOnClickListener(this);
    }

    @Override
    public int getItemCount() {
        return data == null ? 0 : data.size();
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.item_text:
                mOnItemClickListener.onItemClick(v, (int) v.getTag());
                break;
        }
    }

    //自定义的ViewHolder,持有每个Item的的所有界面元素
    public static class ViewHolder extends RecyclerView.ViewHolder {
        public TextView mTextView;

        public ViewHolder(View view) {
            super(view);
            mTextView = (TextView) view.findViewById(R.id.item_text);
        }
    }

    public void removeItem(int position) {
        data.remove(position);
        notifyItemRemoved(position);
        // 加入如下代码保证position的位置正确性
        if (position != data.size() - 1) {
            notifyItemRangeChanged(position, data.size() - position);
        }
    }

    public void addItem(String content, int position) {
        data.add(position, content);
        notifyItemInserted(position);
        // 加入如下代码保证position的位置正确性
        if (position != data.size() - 1) {
            notifyItemRangeChanged(position, data.size() - position);
        }
    }

    public interface OnItemClickLitener {
        void onItemClick(View view, int position);
    }
}

6.完整代码下载地址如下所示:

demo下载地址链接

如有错误欢迎指出来,一起学习。
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值