Android高级UI开发(二)RecyclerView控件使用----列表项的单击事件、添加(删除)列表项
上篇文章介绍了RecyclerView控件的基本用法,我们已经知道它是一个ListView的升级版,可轻松的展示各种列表风格,例如水平列表、垂直列表、网格列表、瀑布流列表等。但是,我们项目中仅仅展示数据是不够的,我们经常还有列表项的单击事件、添加列表项、删除列表项等。今天我们就着重讲解一下RecyclerView列表项的单击事件、添加列表项、删除列表项。
效果:
1. RecyclerView列表项的单击事件
不幸的是RecyclerView控件没有与ListView一样的 onItemClickListener单击事件监听器,那么就需要我们自定义onItemClickListener。我们先贴出MyRecyclerAdapter源码(在上一篇源码基础上修改,用来给RecyclerView装配数据的adapter)
-
package com.anyikang.volunteer.sos.recyclerview;
-
-
import android.support.v7.widget.RecyclerView;
-
import android.view.View;
-
import android.view.ViewGroup;
-
import android.widget.TextView;
-
-
import java.util.List;
-
-
public class MyRecyclerAdapter extends RecyclerView.Adapter<MyRecyclerAdapter.MyViewHolder> {
-
-
private List<String> list; //列表数据
-
private OnItemClickListener mOnItemClickListener;
-
-
public MyRecyclerAdapter(List<String> list) {
-
// TODO Auto-generated constructor stub
-
this.list = list;
-
}
-
-
/**
-
*
-
* 实例化 列表项布局中的控件,在此为一个简单的textview
-
*/
-
class MyViewHolder extends RecyclerView.ViewHolder{
-
TextView tv;
-
-
public MyViewHolder(View view) {
-
super(view);
-
tv = (TextView)view.findViewById(R.id.text1);
-
}
-
-
}
-
-
/**
-
* 要显示的列表项数
-
* @return 列表项总数
-
*/
-
@Override
-
public int getItemCount() {
-
// TODO Auto-generated method stub
-
return list.size();
-
}
-
-
/**
-
* 用数据填充列表项上的 textview文本
-
* @param holder: 当前列表项 布局的 控件实例
-
* @param position: 列表项的索引
-
*/
-
@Override
-
public void onBindViewHolder(MyViewHolder holder, final int position) {
-
holder.tv.setText(list.get(position)); //将列表数据list数组中的position位置的字符串 填充给 这个列表项上的textview
-
-
//实现列表item单击事件,主要使用java interface来实现回调MainActivity中的onItemClick函数
-
if(mOnItemClickListener!=null){
-
holder.itemView.setOnClickListener(new View.OnClickListener() {
-
-
@Override
-
public void onClick(View v) {
-
mOnItemClickListener.onItemClick(v, position);
-
}
-
});
-
}
-
}
-
-
-
/**
-
* 为列表项实例化布局,将在onBindViewHolder里为布局控件赋值
-
* @param viewGroup
-
* @param arg1
-
* @return
-
*/
-
@Override
-
public MyViewHolder onCreateViewHolder(ViewGroup viewGroup, int arg1) {
-
MyViewHolder holder = new MyViewHolder(View.inflate(viewGroup.getContext(), R.layout.list_item, null));
-
return holder;
-
}
-
-
public interface OnItemClickListener{
-
void onItemClick(View view, int position);
-
}
-
-
public void setOnItemClickListener(OnItemClickListener listener){
-
this.mOnItemClickListener = listener;
-
}
-
}
红色标注的代码,就实现了一个列表单击监听器。我们先回顾一下listview的itemOnclickListener在代码中是如何运用的:
//listview列表项单击事件,放在一个Activity里,例如MainActivity
-
lvFence.setOnItemClickListener(new AdapterView.OnItemClickListener() {
-
@Override
-
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
//在这里添加单击处理代码
-
return;
-
}
-
});
上述代码通过调用listview的setOnItemClickListener函数为listview设置了一个 单击监听器OnItemClickListener类对象,
我们从中能分析到什么?
(1)Listview类里有一个成员变量,该成员变量是一个OnItemClickListener类的实例对象。同时,有一个setOnItemClickListener函数来设置该成员变量的具体实例值。
(2)从new AdapterView.OnItemClickListener()这行代码可以猜测OnItemClickListener可能是定义在ListView类中的一个抽象接口,需要在MainActivity里通过 实现(实例化)这个接口以及它包含的抽象函数onItemClick 来处理业务逻辑。当ListView列表项被单击时,ListView会调用OnItemClickListener类型的成员对象(已通过setOnItemClickListener赋值)的 onItemClick函数,由于onItemClick函数实质是在MainActivity里实现的,因此onItemClick的处理代码将在MainActivity里执行,这也就是我们通常所说的“回调”,即在MainActivity里先实现抽象函数,这时并没有调用,而是在恰当的时机回过头来调用onItemClick函数。
综合(1)(2)分析类比,我们为RecyclerView控件自定义了列表项监听功能,具体步骤如下:
第一步,在适配器MyRecyclerAdapter类里定义抽象接口“OnItemClickListener”,其中有一个抽象函数OnItemClick。
第二步,在适配器MyRecyclerAdapter类声明一个OnItemClickListener类型的成员变量与setOnItemClickListener函数。
第三步,在Activity(例如MainActivity)里实现化接口OnItemClickListener及OnItemClick函数,并调用setOnItemClickListener函数为MyRecyclerAdapter中的OnItemClickListener类型成员变量赋值。
第四步,回调。在MyRecyclerAsetOnClickListenerdapter的onBindViewHolder函数里为列表项对应的VIEW布局的单击函数
(这个系统里已经有了,就是普通的按钮单击事件处理)里回调onItemClick函数,具体核心代码如下:
-
//实现列表item单击事件,主要使用java interface来实现回调MainActivity中的onItemClick函数
-
if(mOnItemClickListener!=null){
-
holder.itemView.setOnClickListener(new View.OnClickListener() {
-
-
@Override
-
public void onClick(View v) {
-
mOnItemClickListener.onItemClick(v, position);
-
}
-
});
-
}
到此,为RecyclerView控件补充我们自定义的列表项单击事件分析完毕,具体源码在文章最后。
2. RecyclerView添加、删除列表项与高效更新
当我们更新RecyclerView控件的列表数据时,以往的作法有如下:
(1)setAdapter ,为控件配置数据适配器,同时刷新全部列表项
(2)notifyDataSetChanged 刷新全部列表项数据
以上2种作法比较影响效率,RecyclerView控件为我们提供了 更有效率的两个刷新列表项函数:
函数1----public final void notifyItemInserted(int position)
用于在某一个列表项位置position上新添加一个列表项的情况下刷新列表。示例代码如下:
list.add(position,"additem"+position); //在列表数据数组List<String>的position位置上添加一个新数据
//notifyDataSetChanged();--会影响效率=
notifyItemInserted(position);
其中notifyItemInserted(position)不会重新刷新整个列表数据,只是在position位置上新绘制一个列表项,同时原来
position位置上的列表项的索引 变为position + 1,即从原position位置开始的列表项统一后移。
函数2--notifyItemRemoved(int position)
list.remove(position,"additem"+position); //在列表数据数组List<String>的position位置上删除一个新数据
//notifyDataSetChanged();--会影响效率=
notifyItemRemoved(position);
其中notifyItemInserted(position)不会重新刷新整个列表数据,只是在position位置上删除一个列表项,
同时原来position+1位置上的列表项的索引 变为position,即从原position+1位置开始的列表项统一前移。
完整的代码先贴出来:
布局文件:
-
RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-
xmlns:tools="http://schemas.android.com/tools"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent"
-
>
-
-
<android.support.v7.widget.RecyclerView
-
android:id="@+id/recylerview"
-
android:layout_width="match_parent"
-
android:layout_height="400dp"
-
/>
-
-
<LinearLayout
-
android:layout_marginTop="30dp"
-
android:layout_below="@+id/recylerview"
-
android:orientation="horizontal"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent">
-
-
<Button
-
android:id="@+id/btAdd"
-
android:text="添加"
-
android:layout_width="wrap_content"
-
android:layout_height="wrap_content" />
-
-
<Button
-
android:layout_marginLeft="20dp"
-
android:id="@+id/btDelete"
-
android:text="删除"
-
android:layout_width="wrap_content"
-
android:layout_height="wrap_content" />
-
</LinearLayout>
-
-
</RelativeLayout>
MainActivity代码:
-
package com.anyikang.volunteer.sos.recyclerview;
-
-
import android.app.Activity;
-
import android.os.Bundle;
-
import android.support.v7.widget.DefaultItemAnimator;
-
import android.support.v7.widget.LinearLayoutManager;
-
import android.support.v7.widget.RecyclerView;
-
import android.support.v7.widget.StaggeredGridLayoutManager;
-
import android.view.View;
-
import android.widget.Button;
-
import android.widget.Toast;
-
-
import com.anyikang.volunteer.sos.recyclerview.MyRecyclerAdapter.OnItemClickListener;
-
-
import java.util.ArrayList;
-
-
public class MainActivity extends Activity {
-
-
private RecyclerView recylerview; //RecyclerView控件实例对象
-
private ArrayList<String> list; //RecyclerView要显示的 列表数据,在此为一组字符串。
-
private MyRecyclerAdapter adapter; //同ListView一样,需要一个适配器来 将list数据 装载到 RecyclerView列表控件。
-
//private MyStaggedRecyclerAdapter adapter; //列表显示风格 为瀑布流 界面样式 的 适配器。
-
boolean isGrid = true;
-
-
@Override
-
protected void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
setContentView(R.layout.activity_main);
-
initView();
-
initData();
-
}
-
-
public void initView()
-
{
-
//实例化布局中的recylerview控件
-
recylerview = (RecyclerView)findViewById(R.id.recylerview);
-
Button btAdd = findViewById(R.id.btAdd);
-
Button btDelete = findViewById(R.id.btDelete);
-
Button btConvert = findViewById(R.id.btConvert);
-
-
btAdd.setOnClickListener(new View.OnClickListener() {
-
@Override
-
public void onClick(View view) {
-
adapter.addData(3);
-
}
-
});
-
-
btDelete.setOnClickListener(new View.OnClickListener() {
-
@Override
-
public void onClick(View view) {
-
adapter.removeData(3);
-
}
-
});
-
}
-
-
public void initData()
-
{
-
-
//模拟60条数据
-
list = new ArrayList<String>();
-
-
for (int i = 0; i < 60; i++) {
-
list.add("item"+i);
-
}
-
-
-
//普通列表的适配器
-
adapter = new MyRecyclerAdapter(list);
-
-
//列表显示风格为 垂直方向的列表
-
//recylerview.setLayoutManager(new LinearLayoutManager(this));
-
-
//列表显示风格为 水平方向的列表
-
//recylerview.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, true));
-
-
//列表显示风格为 瀑布流样式
-
recylerview.setLayoutManager(new StaggeredGridLayoutManager(3, LinearLayoutManager.VERTICAL));
-
-
//列表显示风格为 网格样式,如9宫格布局
-
//recylerview.setLayoutManager(new GridLayoutManager(this, 3));
-
//瀑布流适配器,与普通适配器adapter的区别是,每一个列表项的布局大小都可能参差不齐
//adapter = new MyStaggedRecyclerAdapter(list);
//装载显示列表数据 recylerview.setAdapter(adapter); recylerview.setItemAnimator(new DefaultItemAnimator());//添加删除列表项时会有动画效果,具体运行源码查看。 adapter.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(View view, int position) { Toast.makeText(MainActivity.this, "点了"+position, Toast.LENGTH_SHORT).show(); } }); return; }}
adapter代码:
-
package com.anyikang.volunteer.sos.recyclerview;
-
-
import android.support.v7.widget.RecyclerView;
-
import android.view.View;
-
import android.view.ViewGroup;
-
import android.widget.TextView;
-
-
import java.util.List;
-
-
public class MyRecyclerAdapter extends RecyclerView.Adapter<MyRecyclerAdapter.MyViewHolder> {
-
-
private List<String> list; //列表数据
-
private OnItemClickListener mOnItemClickListener;
-
-
public MyRecyclerAdapter(List<String> list) {
-
// TODO Auto-generated constructor stub
-
this.list = list;
-
}
-
-
/**
-
*
-
* 实例化 列表项布局中的控件,在此为一个简单的textview
-
*/
-
class MyViewHolder extends RecyclerView.ViewHolder{
-
TextView tv;
-
-
public MyViewHolder(View view) {
-
super(view);
-
tv = (TextView)view.findViewById(R.id.text1);
-
}
-
-
}
-
-
/**
-
* 要显示的列表项数
-
* @return 列表项总数
-
*/
-
@Override
-
public int getItemCount() {
-
// TODO Auto-generated method stub
-
return list.size();
-
}
-
-
/**
-
* 用数据填充列表项上的 textview文本
-
* @param holder: 当前列表项 布局的 控件实例
-
* @param position: 列表项的索引
-
*/
-
@Override
-
public void onBindViewHolder(MyViewHolder holder, final int position) {
-
holder.tv.setText(list.get(position)); //将列表数据list数组中的position位置的字符串 填充给 这个列表项上的textview
-
-
//实现列表item单击事件,主要使用java interface来实现回调MainActivity中的onItemClick函数
-
if(mOnItemClickListener!=null){
-
holder.itemView.setOnClickListener(new View.OnClickListener() {
-
-
@Override
-
public void onClick(View v) {
-
mOnItemClickListener.onItemClick(v, position);
-
}
-
});
-
}
-
}
-
-
-
/**
-
* 为列表项实例化布局,将在onBindViewHolder里为布局控件赋值
-
* @param viewGroup
-
* @param arg1
-
* @return
-
*/
-
@Override
-
public MyViewHolder onCreateViewHolder(ViewGroup viewGroup, int arg1) {
-
MyViewHolder holder = new MyViewHolder(View.inflate(viewGroup.getContext(), R.layout.list_item, null));
-
return holder;
-
}
-
-
-
public void addData(int position){
-
list.add(position,"additem"+position);
-
//提示刷新--会影响效率
-
// notifyDataSetChanged();
-
notifyItemInserted(position);
-
}
-
public void removeData(int position){
-
list.remove(position);
-
notifyItemRemoved(position);
-
}
-
-
public interface OnItemClickListener{
-
void onItemClick(View view, int position);
-
}
-
-
public void setOnItemClickListener(OnItemClickListener listener){
-
this.mOnItemClickListener = listener;
-
}
}
完整的工程源码下载地址:https://download.csdn.net/download/gaoxiaoweiandy/10364579
文章来源: blog.csdn.net,作者:冉航--小虾米,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/gaoxiaoweiandy/article/details/79968066
- 点赞
- 收藏
- 关注作者
评论(0)