RecycleView简单使用
来源:互联网 发布:淘宝号不要了怎么注销 编辑:程序博客网 时间:2024/06/15 22:56
- 简介
- 基本使用流程
- 导包
- 设置布局管理器
- 设置Adapter
- 添加分割线
- 设置动画
- 点击事件
- HeadView FootView
- 复杂布局层数简化
- 布局要求
- 布局解析
- 布局实现
- 最终效果展示
简介
A flexible view for providing a limited window into a large data set.
一个展示大量数据、灵活的View控件。
个人理解为ListView、GridView的官方升级版本,将ViewHolder、复用itemView等ListView优化方案吸收,更加灵活、解耦的展示大量数据。
2017.11.20 增加推荐点击事件处理、HeadView+FootView的封装.
基本使用流程
1.导包
使用RecycleView需要引入v7包对应。
// 版本号跟v7包版本号一致就行compile 'com.android.support:recyclerview-v7:xx.x.x'
2.设置布局管理器
RecycleView.setLayoutManager(LayoutManager);
自带的三个布局管理器:
StaggeredGridLayoutManager : 流式布局管理器
A LayoutManager that lays out children in a staggered grid formation.
It supports horizontal & vertical layout as well as an ability to layout children in reverse..
以交错网格的形式布局,支持水平和垂直布局,同时支持反向。
LinearLayoutManager:线性布局管理器
similar functionality to {@link android.widget.ListView}
官方解释:功能和ListView类似。。。
GridLayoutManager:表格布局管理器
By default, each item occupies 1 span. You can change it by providing a custom
{@link SpanSizeLookup} instance via {@link #setSpanSizeLookup(SpanSizeLookup)}.
默认每个Item占据一个跨度(span:表格的列数既定之后,每个item的宽度),但是你可以setSpanSizeLookup()方法修改每个item的跨度。
功能类似于GridView,继承了LinearLayoutManager,但是官方的解释上面是重点,通过上面的功能能够实现更加灵活的表格布局,将往常只能嵌套使用的布局在不嵌套的情况展示。
3.设置Adapter
RecycleView.setAdapter();
adapter必须重写方法如下:
new RecyclerView.Adapter() { /** * 根据viewType返回想要的ViewHolder,强行绑定ListView中ViewHolder模式。 * * 每个Item都会调用仅且调用一次,即每个Item的ViewHolder对象都不被其他Item(即使类型相同)复用。 * 这里与ListView使用ViewHolder有所区别。 * * 当Item需要被复用,调用方法{@link #onBindViewHolder(RecyclerView.ViewHolder, int)} */ @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item1, parent, false); RecyclerViewAdapter1.ViewHolder viewHolder = new RecyclerViewAdapter1.ViewHolder(view); return viewHolder; } /** * 根据加载位置进行数据展示 * 当Item被展示到屏幕上时调用,进行Item展示、更新 */ @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { } /** * 返回总的Item数量 */ @Override public int getItemCount() { return 0; }});
4. 添加分割线
RecycleView.addItemDecoration(RecyclerView.ItemDecoration);
以前添加分割线的方法不再有效。
android:divider="#ff0000"android:dividerHeight="1dp"
自定义分割线
new RecyclerView.ItemDecoration() { /** * 调用在绘制Item之前 * 一般情况两个Draw方法选一个重写即可 */ @Override public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { } /** * 调用在绘制Item之后 */ @Override public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { } /** * 设置偏移量 */ @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { // 对Item进行偏移 outRect.set(0,0,0,8); }});
5. 设置动画
RecyclerView.setItemAnimator(new DefaultItemAnimator());
这里使用默认的系统动画。
同时调用如下方法进行Item的add和remove:
public void addItem(int position, String s){ arrayList.add(position,s); notifyItemInserted(position);}public void remove(int position){ arrayList.remove(position); notifyItemRemoved(position);}
6.点击事件
方式一:由于RecycleView没有直接给出点击事件的接口,可以将事件监听接口放到Adapter中,在布局容器进行实现,容器中调用就好了,这里不做实现。
方式二(推荐使用):RxJava PublishSubject实现监听事件的传递。
没有使用RxJava不能使用!!!
adapter实现:
private final PublishSubject<Model> onClickSubject = PublishSubject.create();/*** 点击事件 进行订阅** @author fengzhen* @version v6.3.0, 2017/11/18 17:43*/public PublishSubject<Model> getOnClickSubject() { return onClickSubject;}@Overridepublic void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { Model model = mListData.get(position); ViewHolder viewHolder = (ViewHolder) holder; viewHolder.mTvContent.setOnClickListener(v -> onClickSubject.onNext(model));}
外部订阅:
mXXXAdapter.getOnClickSubject().subscribe(new DefaultSubscriber<Model>() { @Override public void onNext(Modeldata) { // 点击事件处理 showShortToast(data.getString()); } });
好,就酱!
7.HeadView + FootView
从ListView到RecyclerView怎么能把很常用的HeadView、FootView给忘了。
这里直接贴封装的一个简单Adapter,使用直接继承My Adapter 就可以直接用了。
import android.support.v7.widget.RecyclerView;import android.view.View;import android.view.ViewGroup;/** * 扩展RecyclerView.Adapter * 添加HeadView、FootView * * @author fengzhen * @version v6.3.0, 2017/11/20 */public abstract class RecyclerViewExtendAdapter extends RecyclerView.Adapter { public static final int ITEM_TYPE_HEADVIEW = 999; public static final int ITEM_TYPE_FOOTVIEW = 998; private View mHeadview; private View mFootview; private boolean hasHeadView = false; public void setHeadview(View headview) { hasHeadView = headview != null; this.mHeadview = headview; notifyDataSetChanged(); } public void setFootview(View footview) { this.mFootview = footview; notifyDataSetChanged(); } public View getmHeadview() { return mHeadview; } public View getmFootview() { return mFootview; } /** * 不可重写, * 重写方法{@link RecyclerViewExtendAdapter#getNormalItemViewType}实现具体子类操作 * * @author fengzhen * @version v6.3.0, 2017/11/20 15:57 */ @Override public final int getItemViewType(int position) { if (mHeadview != null && position < 1) { return ITEM_TYPE_HEADVIEW; } else if (mFootview != null && position == getItemCount() - 1) { return ITEM_TYPE_FOOTVIEW; } else { return getNormalItemViewType(hasHeadView ? position - 1 : position); } } /** * 子类实现此方法,等同于直接实现{@link RecyclerView.Adapter#getItemViewType(int)} ()} * * @return The view type of this ViewHolder. * @author fengzhen * @version v6.3.0, 2017/11/20 15:52 */ protected int getNormalItemViewType(int position) { return super.getItemViewType(position); } /** * 不可重写 * 子类实现{@link RecyclerViewExtendAdapter#getNormalItemCount()} * * @author fengzhen * @version v6.3.0, 2017/11/20 16:10 */ @Override public final int getItemCount() { return getNormalItemCount() + (mHeadview == null ? 0 : 1) + (mFootview == null ? 0 : 1); } /** * 子类实现此方法,等同于实现{@link RecyclerView.Adapter#getItemCount()} * * @author fengzhen * @version v6.3.0, 2017/11/20 16:06 */ protected abstract int getNormalItemCount(); /** * 不可重写 * 子类实现{@link RecyclerViewExtendAdapter#onNormalCreateViewHolder(ViewGroup, int)} * * @author fengzhen * @version v6.3.0, 2017/11/20 16:10 */ @Override public final RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { switch (viewType) { case ITEM_TYPE_HEADVIEW: return new HeadViewHolder(mHeadview); case ITEM_TYPE_FOOTVIEW: return new FootViewHolder(mFootview); default: return onNormalCreateViewHolder(parent, viewType); } } /** * 子类实现此方法,等同于实现{@link RecyclerView.Adapter#onCreateViewHolder(ViewGroup, int)} * * @author fengzhen * @version v6.3.0, 2017/11/20 16:06 */ protected abstract RecyclerView.ViewHolder onNormalCreateViewHolder(ViewGroup parent, int viewType); /** * 不可重写 * 子类实现{@link RecyclerViewExtendAdapter#onNormalBindViewHolder(RecyclerView.ViewHolder, int, int)} * * @author fengzhen * @version v6.3.0, 2017/11/20 16:10 */ @Override public final void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { int itemViewType = getItemViewType(position); switch (itemViewType) { case ITEM_TYPE_HEADVIEW: case ITEM_TYPE_FOOTVIEW: break; default: onNormalBindViewHolder(holder, hasHeadView ? position - 1 : position, itemViewType); break; } } /** * 子类实现此方法,等同于实现{@link RecyclerView.Adapter#onBindViewHolder(RecyclerView.ViewHolder, int)} * * @author fengzhen * @version v6.3.0, 2017/11/20 16:06 */ protected abstract void onNormalBindViewHolder(RecyclerView.ViewHolder holder, int position, int itemViewType); private class HeadViewHolder extends RecyclerView.ViewHolder { public HeadViewHolder(View itemView) { super(itemView); } } private class FootViewHolder extends RecyclerView.ViewHolder { public FootViewHolder(View view) { super(view); } }}
复杂布局层数简化
1. 布局要求
实现如下的布局:
2. 布局解析
实现方式一: 直接硬布局,最外层用一个ScrollView,里面用 TextView + ListView + TextView + GridView。还需要对ListView和GridView进行重写测量方法,才能实现效果。
实现方式二: 整个作为一个ListView,Title、ListView 、GridView都看成是父ListView 的一个Item。但是对于其中的交互逻辑的代码不要控制,写出来肯定很不“优美”。
实现方式三: 使用RecycleView的GridLayoutManager布局,通过item type 设置,将Title、ListVite item和GridView item都作为RecycleView 的item,使用一层布局,这也是推荐的做法。
3. 布局实现
实现布局的重点在于GridLayoutManager的setSpanSizeLookup()方法。
设置布局管理器:
// 设置布局管理器private void initLayout() { // 这里的4,取所需列数的最小公倍数 mRecyclerView1.setLayoutManager(new GridLayoutManager(this, 4));}
Adapter实现:
/** * Created by fengzhen. * * recyclerView 适配器 */public class RecyclerViewAdapter1 extends RecyclerView.Adapter<RecyclerViewAdapter1.ViewHolder> { // 布局类型 public static final int TITLE_1 = 0x0; public static final int TITLE_2 = 0x1; public static final int LINEAR_1 = 0x2; public static final int GRID_2 = 0x3; // 数据集 private List<String> arrayList; public RecyclerViewAdapter1(List<String> list) { arrayList = list; } /** * 查找item布局,强制绑定ViewHolder */ @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { // 没做类型判定 需要时判断 viewType View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item1, parent, false); return new ViewHolder(view); } /** * 根据加载位置进行数据展示 */ @Override public void onBindViewHolder(ViewHolder holder, int position) { // 没做类型判定 需要时判断 viewType holder.textView1.setText(arrayList.get(position)); } /** * 实现布局的重点 */ @Override public void onAttachedToRecyclerView(RecyclerView recyclerView) { super.onAttachedToRecyclerView(recyclerView); /** * 处理GridLayoutManager布局 * LayoutManager列数设置为 所有可能出现的列数的最小公倍数 * 具体的列数,返回在总列数的比例 * 例:可能出现的列数有: 1、3、4、7 * LayoutManager的列数设置为 : 1*3*4*7 = 84; * 对应列数的返回值: 84、 28、21、12; */ RecyclerView.LayoutManager manager = recyclerView.getLayoutManager(); if(manager instanceof GridLayoutManager) { final GridLayoutManager gridManager = ((GridLayoutManager) manager); gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { int type = getItemViewType(position); switch (type){ case TITLE_1: case TITLE_2: return 4; case LINEAR_1: return 1; case GRID_2: return 2; default: return 4; } } }); } } /** * 返回不同的类型 * * @author fengzhen * @version v1.0, 2017/8/23 15:47 */ @Override public int getItemViewType(int position) { if (position == 0) { return TITLE_1; } else if (position < 8) { return LINEAR_1; } else if (position == 8) { return TITLE_2; } else { return GRID_2; } } /** * 类似listview中的方法,获取总item数 */ @Override public int getItemCount() { return arrayList.size(); } /** * 继承RecycleView的ViewHolder,对item控件进行初始化 */ public static class ViewHolder extends RecyclerView.ViewHolder { public TextView textView1; public ViewHolder(View itemView) { super(itemView); textView1 = (TextView) itemView.findViewById(R.id.textView1); } }}
4. 最终效果展示
- RecycleView的简单使用
- RecycleView简单使用
- RecycleView简单使用
- RecycleView 的简单使用
- RecycleView简单使用
- 简单使用recycleView
- RecycleView的简单使用
- RecycleView简单使用
- RecycleView的简单使用
- Android RecycleView---- RecycleView的简单使用
- Android 开发之RecycleView的简单使用
- 使用recycleview实现简单的柱状图
- android:RecycleView的简单封装使用
- RecycleView使用
- RecycleView使用
- recycleview使用
- 使用RecycleView时候的adapter的简单封装
- RecycleView简单介绍
- request.getParameter乱码
- Java Web 学习笔记之十一:RestEasy统一处理异常
- groovy动态语言
- zookeeper伪集群安装
- C#中的并行与多线程编程
- RecycleView简单使用
- 外网访问本机apache的配置
- JS/CSS Minify(uglify) and Prettify
- java 中的接口和抽象类的异同
- docker下gdb调试断点不停
- 数据结构-树 总结
- Android Studio 开发之NDK混合开发的应用
- NoSQL
- JAVA NIO(三):缓冲区的相互转换及中文乱码的解决方案