Android RecyclerView的使用
一:RecyclerView是什么
从Android5.0开始,谷歌推出一个用于大量数据展示的新控件RecyclerView,可以替代传统的ListView,更加强大和灵活。
在AndroidX项目中添加依赖:implementation 'androidx.recyclerview:recyclerview:1.1.0'
在非AndroidX项目中添加依赖:implementation 'com.android.support:recyclerview-v7:26.1.0'//对应的是compileSdkVersion的版本
//Android布局使用
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent" />
//AndroidX布局使用
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"/>
RecyclerView的优点
1.支持局部刷新
2.可以自定义Item增删时的动画
3.能够实现Item拖拽和侧滑删除等功能
二:RecyclerView使用
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/tv_recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
1.创建布局管理器
LinearLayoutManager:线性布局,以垂直或水平滚动方式显示列表
GridLayoutManager:网格布局,在网格中显示项目
StaggeredGridLayoutManager:瀑布流布局,在分散对齐网格中显示项目
LinearLayoutManager layoutManager=new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false);//线性布局管理器
GridLayoutManager gridLayoutManager=new GridLayoutManager(this,3);//网格布局管理器
StaggeredGridLayoutManager staggeredGridLayoutManager=new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);//瀑布流布局
2.适配器使用
public class MyRecycleViewAdapter extends RecyclerView.Adapter<MyRecycleViewAdapter.MyHolder> {
private List<String> mDatas;//数据源
private Context context;
private OnItemClickListener onItemClickListener;
/**向外部提供调用设置监听*/
public void setOnItemClickListener(OnItemClickListener onItemClickListener){
this.onItemClickListener=onItemClickListener;
}
public MyRecycleViewAdapter(Context context,List<String> mDatas) {
this.context=context;
this.mDatas = mDatas;
}
/**
* 创建ViewHolder并返回,后续item布局里控件都是从ViewHolder中取出
*/
@NonNull
@Override
public MyHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
//将我们自定义的item布局转成View
View view = LayoutInflater.from(context).inflate(R.layout.item_one, parent, false);
//将View传递给我们自定义ViewHolder
return new MyHolder(view);
}
/**通过方法提供的ViewHolder,将数据绑定到的ViewHolder中*/
@Override
public void onBindViewHolder(@NonNull MyHolder holder, int position) {
holder.tv_content.setText(mDatas.get(position));
holder.tv_content.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (onItemClickListener!=null){
onItemClickListener.onItemClick(v,holder.getAdapterPosition()+1);
}
}
});
}
/**
* 获取数据源总的条目
*/
@Override
public int getItemCount() {
return mDatas.size();
}
static class MyHolder extends RecyclerView.ViewHolder {
TextView tv_content;
public MyHolder(@NonNull View itemView) {
super(itemView);
tv_content=itemView.findViewById(R.id.tv_content);
}
}
/**自定义的接口*/
public interface OnItemClickListener{
void onItemClick(View view,int position);
}
}
RecyclerView 封装了viewholder的回收复用,标准化了ViewHolder,编写Adapter面向的是ViewHolder而不是View,复用的逻辑封装了
创建适配器步骤:
1.创建Adapter:创建一个继承RecyclerView.Adapter<VH>的Adapter类(VH是ViewHolder的类名)
2.创建ViewHolder:在Adapter中创建一个继承RecyclerView.ViewHolder的静态内部类,记为VH。ViewHolder的实现和ListView的ViewHolder实现几乎一样。
三个方法:
onCreateViewHolder: 创建ViewHolder并返回,后续item布局里控件都是从ViewHolder中取出。
onBindViewHolder:通过方法提供的ViewHolder,将数据绑定到ViewHolder中。
getItemCount:获取数据源总的条数。
上面2个适配器和布局管理器是必须设置的
3.Item Decoration(可选)设置分割线
//添加分割线
tv_recycler.addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.VERTICAL));//默认的分割线
可以自定义间隔样式需要继承RecyclerView.ItemDecoration类,该类是抽象类
public class MyItemDecoration extends RecyclerView.ItemDecoration {
private final Drawable mLine;
private final int orientation;
public MyItemDecoration(Context context, int orientation) {
this.orientation = orientation;
int[] attrs = new int[]{android.R.attr.listDivider};//系统的分割线颜色
TypedArray a = context.obtainStyledAttributes(attrs);
mLine = a.getDrawable(0);
a.recycle();
}
/**在Item绘制之前被调用,用于绘制间隔样式*/
@Override
public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.onDraw(c, parent, state);
if (orientation==RecyclerView.HORIZONTAL){
drawVertical(c, parent, state);
}else if (orientation==RecyclerView.VERTICAL){
drawHorizontal(c, parent, state);
}
}
/**onDraw和onDrawOver2个其中一个就行*/
@Override
public void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.onDrawOver(c, parent, state);
}
/**设置item的偏移量,偏移的部分用于填充间隔样式,即设置分割线的宽、高;在RecyclerView的onMesure()中会调用该方法。*/
@Override
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
if (orientation == RecyclerView.HORIZONTAL) {
//画垂直线
outRect.set(0, 0, mLine.getIntrinsicWidth(), 0);
} else if (orientation == RecyclerView.VERTICAL) {
//画水平线
outRect.set(0, 0, 0, mLine.getIntrinsicHeight());
}
}
/**
* 画垂直分割线
*/
private void drawVertical(Canvas c, RecyclerView parent, RecyclerView.State state) {
int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
View child = parent.getChildAt(i);
int left = child.getRight();
int top = child.getTop();
int right = left + mLine.getIntrinsicWidth();
int bottom = child.getBottom();
mLine.setBounds(left, top, right, bottom);
mLine.draw(c);
}
}
/**
* 画水平分割线
*/
private void drawHorizontal(Canvas c, RecyclerView parent, RecyclerView.State state) {
int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
View child = parent.getChildAt(i);
int left = child.getLeft();
int top = child.getBottom();
int right = child.getRight();
int bottom = top + mLine.getIntrinsicHeight();
mLine.setBounds(left, top, right, bottom);
mLine.draw(c);
}
}
}
我们可以修改系统自定义分割线颜色
在res下values下theme主题中
<!--自定义系统分割线颜色-->
<item name="android:listDivider">@drawable/customizelistdivider </item>
在res/drawable中设置customizelistdivider
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:endColor="#ff0000ff"
android:startColor="#ffff0000"
android:type="linear" />
<size android:height="4dp"
android:width="4dp"/>
</shape>
使用设置自定义分割线
tv_recycler.addItemDecoration(new MyItemDecoration(this,RecyclerView.VERTICAL));
4.ItemAnimator动画(可选)
tv_recycler.setItemAnimator(new DefaultItemAnimator());//设置默认动画
默认动画继承DefaultItemAnimator来实现自定义动画
相关实现
public class SecondActivity extends AppCompatActivity {
private RecyclerView tv_recycler;
private MyRecycleViewAdapter myRecycleViewAdapter;
private List<String> mDatas=new ArrayList<>();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
initData();//初始化数据
tv_recycler=findViewById(R.id.tv_recycler);
//创建布局管理器
LinearLayoutManager layoutManager=new LinearLayoutManager(this);//默认垂直排列
//GridLayoutManager gridLayoutManager=new GridLayoutManager(this,3);
//StaggeredGridLayoutManager staggeredGridLayoutManager=new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);
layoutManager.setOrientation(RecyclerView.HORIZONTAL);//设置水平排列
//LinearLayoutManager layoutManager1=new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false);
//设置布局管理器
tv_recycler.setLayoutManager(layoutManager);
//添加分割线
tv_recycler.addItemDecoration(new MyItemDecoration(this,RecyclerView.VERTICAL));//自定义分割线
tv_recycler.setItemAnimator(new DefaultItemAnimator());
//tv_recycler.addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.VERTICAL));//默认的分割线
//创建数据适配器
myRecycleViewAdapter=new MyRecycleViewAdapter(this,mDatas);
//设置数据适配器
tv_recycler.setAdapter(myRecycleViewAdapter);
//外部适配器数据监听条目点击
myRecycleViewAdapter.setOnItemClickListener(new MyRecycleViewAdapter.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
Toast.makeText(SecondActivity.this, "第"+position+"条数据", Toast.LENGTH_SHORT).show();
}
});
}
private void initData() {
for (int i=0;i<40;i++){
mDatas.add("我是item"+i);
}
}
}
5.Item条目监听,点击事件监听
/**向外部提供调用设置监听*/
public void setOnItemClickListener(OnItemClickListener onItemClickListener){
this.onItemClickListener=onItemClickListener;
}
public MyRecycleViewAdapter(Context context,List<String> mDatas) {
this.context=context;
this.mDatas = mDatas;
}
/**自定义的接口*/
public interface OnItemClickListener{
void onItemClick(View view,int position);
}
@Override
public void onBindViewHolder(@NonNull MyHolder holder, int position) {
holder.tv_content.setText(mDatas.get(position));
holder.tv_content.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (onItemClickListener!=null){
onItemClickListener.onItemClick(v,holder.getAdapterPosition()+1);//在绑定数据的时候给外部传递得postion从1开始
}
}
});
}
//外部调用开始
myRecycleViewAdapter.setOnItemClickListener(new MyRecycleViewAdapter.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
Toast.makeText(SecondActivity.this, "第"+position+"条数据", Toast.LENGTH_SHORT).show();
}
});
END:只愿年过半百,归来仍是少年
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。