首页 > 系统 > Android > 正文

Android5.0新控件——RecyclerView的使用全解

2019-11-09 17:33:39
字体:
来源:转载
供稿:网友

介绍

RecyclerView与ListView原理是类似的:都是仅仅维护少量的View并且可以展示大量的数据集。RecyclerView用以下两种方式简化了数据的展示和处理:

使用LayoutManager来确定每一个item的排列方式。 为增加和删除项目提供默认的动画效果。 你也可以定义你自己的LayoutManager和添加删除动画,RecyclerView项目结构如下: 这里写图片描述

Adapter:使用RecyclerView之前,你需要一个继承自RecyclerView.Adapter的适配器,作用是将数据与每一个item的界面进行绑定。 LayoutManager:用来确定每一个item如何进行排列摆放,何时展示和隐藏。回收或重用一个View的时候,LayoutManager会向适配器请求新的数据来替换旧的数据,这种机制避免了创建过多的View和频繁的调用findViewById方法(与ListView原理类似)。

目前SDK中提供了三种自带的LayoutManager:

LinearLayoutManager GridLayoutManager StaggeredGridLayoutManager

recyclerView = (RecyclerView) findViewById(R.id.recyclerView); LinearLayoutManager layoutManager = new LinearLayoutManager(this ); //设置布局管理器 recyclerView.setLayoutManager(layoutManager); //设置为垂直布局,这也是默认的 layoutManager.setOrientation(OrientationHelper. VERTICAL); //设置Adapter recyclerView.setAdapter( recycleAdapter); //设置分隔线 recyclerView.addItemDecoration( new DividerGridItemDecoration(this )); //设置增加或删除条目的动画 recyclerView.setItemAnimator( new DefaultItemAnimator());

①onCreateViewHolder() 这个方法主要生成为每个Item inflater出一个View,但是该方法返回的是一个ViewHolder。该方法把View直接封装在ViewHolder中,然后我们面向的是ViewHolder这个实例,当然这个ViewHolder需要我们自己去编写。直接省去了当初的convertView.setTag(holder)和convertView.getTag()这些繁琐的步骤。

②onBindViewHolder() 这个方法主要用于适配渲染数据到View中。方法提供给你了一个viewHolder,而不是原来的convertView。

③getItemCount() 这个方法就类似于BaseAdapter的getCount方法了,即总共有多少个条目。

高级控件使用讲解的参考博客

这里写图片描述

参考博客,点击查看

简单的RecyclerView使用方法

1、添加依赖

compile 'com.android.support:recyclerview-v7:24.2.1'

2. 使用RecyclerView

<android.support.v7.widget.RecyclerView android:id="@+id/rv" android:layout_width="match_parent" android:layout_height="match_parent" />

3.创建适配器设置给RecyclerView

View view = inflater.inflate(R.layout.fragment_home, container, false); //获取rv控件 RecyclerView rv = (RecyclerView) view.findViewById(R.id.rv); rv.setLayoutManager(new LinearLayoutManager(getContext())); //设置Adapter MyAdapter adapter = new MyAdapter(); rv.setAdapter(adapter); return view;

4.创建适配器

PRivate class MyAdapter extends RecyclerView.Adapter<MyHolder>{ private final List<String> list; public MyAdapter(){ list = new ArrayList<String>(); for (int i = 0; i < 30; i++) { list.add("商品记录" + i)}} //OnCreateViewHolder用来给rv创建缓存的 public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) { //参数3:判断条件 true 1.是打气 2.添加到parent View view = LayoutInflater.from(getContext()).inflate(R.layout.main_recyclerview_item,parent,false); MyHolder holder = new MyHolder(view); return holder; } //给缓存控件设置数据 public void onBindViewHolder(MyHolder holder, int position) { String item = list.get(position); holder.textView.setText(item); holder.icon.setImageResource(R.drawable.ic_default); } //获取记录数 public int getItemCount() { return list.size(); }

5.创建HolderView

public class MyHolder extends RecyclerView.ViewHolder { public ImageView icon; public TextView textView; //实现的方法 public MyHolder(View itemView) { super(itemView); icon= (ImageView) itemView.findViewById(R.id.item_iv_icon); textView= (TextView) itemView.findViewById(R.id.item_tv_title); }}

封装RecyclerView通用适配器

好处:1.数量动态 2.类型不限 Map<Integer,View> 作用:封装了Adapter编写的冗余代码,提供简洁的基类

思路:不写死空间变量,而采用Map方式。 步骤:先关注比较火的控件库 使用一下,看一下好处 学习下底层源代码 自己动手体会 ①封装了BaseHolder

//抽取BaseHolder继承RecyclerView.ViewHolderpublic class BaseHolder extends RecyclerView.ViewHolder { //不写死控件变量,而采用Map方式 private HashMap<Integer, View> mViews = new HashMap<>(); public BaseHolder(View itemView) { super(itemView); } /** *获取控件的方法 */ public<T> T getView(Integer viewId){ //根据保存变量的类型 强转为该类型 View view = mViews.get(viewId); if(view==null){ view= itemView.findViewById(viewId); //缓存 mViews.put(viewId,view); } return (T)view; } /** *传入文本控件id和设置的文本值,设置文本 */ public BaseHolder setText(Integer viewId, String value){ TextView textView = getView(viewId); if (textView != null) { textView.setText(value); } return this; } /** * 传入图片控件id和资源id,设置图片 */ public BaseHolder setImageResource(Integer viewId, Integer resId) { ImageView imageView = getView(viewId); if (imageView != null) { imageView.setImageResource(resId); } return this; } //...还可以扩展出各种控件。 //Fluent API 链式api obj.setxxx().setyyy()....}

②Holder封装好之后,再封装BaseAdapter

封装的时候,部分参数可以选择由外部的构造函数或者set方法 public class BaseAdapter<T> extends RecyclerView.Adapter<BaseHolder> { private List<T> mList = new ArrayList<>(); private int layoutId; public BaseAdapter(int layoutId,List<T> list){ this.layoutId=layoutId; this. mList=list; } //onCreateViewHolder用来给rv创建缓存 @Override public BaseHolder onCreateViewHolder(ViewGroup parent, int viewType) { //参数3 判断条件 true 1.打气 2.添加到paraent // false 1.打气 (参考parent的宽度) View view = LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false); BaseHolder holder = new BaseHolder(view); return holder; } //onBindViewHolder给缓存控件设置数据 @Override public void onBindViewHolder(BaseHolder holder, int position) { T item = mList.get(position); convert(holder,item); } protected void convert(BaseHolder holder, T item) { //什么都没有做 } //获取记录数据 @Override public int getItemCount() { return mList.size(); } }

③封装之后,继承实现

/** *1.extends 把父类的代码继承过来。 可以少写很多代码。 *2.因为是全部拿来的代码,所以不是所有的代码都适合当前。对于不适合当前的代码(方法) * 我们可选择@Override 覆盖|重写 */public class MyHomeAdapter extends BaseAdapter<String> { public MyHomeAdapter(List<String> list) { super(R.layout.main_recyclerview_item, list); } @Override protected void convert(BaseHolder holder, String item) { holder.setText(R.id.item_tv_title,item).setImageResource(R.id.image,R.drawable.ic_default); }}

④封装之后,代码实现

public class HomeFragment extends Fragment { private List<String> list; @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_home, container, false); //获取rv控件 RecyclerView rv = (RecyclerView) view.findViewById(R.id.rv); b rv.setLayoutManager(new LinearLayoutManager(getContext())); initData(); //设置Adapter MyHomeAdapter adapter = new MyHomeAdapter(list); rv.setAdapter(adapter); return view;

案例1

依赖 布局文件activity_recycler_view.xml

<?xml version="1.0" encoding="utf-8"?><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/id_recyclerview" android:divider="#FFB900" android:dividerHeight="1dp" android:layout_width="match_parent" android:layout_height="match_parent"/></RelativeLayout>

让我们来看看变化最大的Adaper:

class HomeAdapter extends RecyclerView.Adapter<HomeAdapter.MyViewHolder>{ private List<String> mList; private Context mContext;; public HomeAdapter(Context mContext,List<String>mList){ this.mContext=mContext; this.mList=mList; } public void removeData(int position) { mList.remove(position); notifyItemRemoved(position); } @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { MyViewHolder holder = new MyViewHolder(LayoutInflater.from( mContext).inflate(R.layout.item_recycler, parent, false)); return holder; } @Override public void onBindViewHolder(final MyViewHolder holder, final int position) { holder.tv.setText(mList.get(position)); } @Override public int getItemCount() { return mList.size(); } class MyViewHolder extends RecyclerView.ViewHolder { TextView tv; public MyViewHolder(View view) { super(view); tv = (TextView) view.findViewById(R.id.tv_item); } }}

最大的改进就是对ViewHolder进行了封装定义,不用自己去自定义了,另外Adaper继承RecyclerView.Adapter,在onCreateViewHolder加载条目布局,在onBindViewHolder中将视图与数据进行绑定。 布局文件item_recycler.xml:

<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:background="@android:color/white" android:layout_height="wrap_content" > <TextView android:id="@+id/tv_item" android:layout_width="match_parent" android:layout_height="50dp" android:gravity="center" android:text="moon" /></FrameLayout>

这里写图片描述

高级进阶—分割线


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表