RecyclerView基本使用可参考:RecyclerView详细介绍(一)
- 前言
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.完整代码下载地址如下所示:
如有错误欢迎指出来,一起学习。