是时候使用RecycleView,RecyclerView的起步封装

必发365游戏官方网址 1test.jpg前些天把recyclerview的中央封装写完了,假如还不精晓链接的地点能够点那些,点那些重头起首,RecyclerView的开发银行封装,写的倒霉的地点恐怕期待大家改进,假如有更加好的建议希望大家时刻@小编,在此谢过各位大神了:话十分的少好正题发轫了,恩恩,先过来下心情:

规矩依旧对不久前一段时间做下计算,看到上面的日记更新时间也许11月,纵然并未过多少人去阅读他,但是那并不可能代表自个儿就不跟着写下去了,作者特别爱怜自个儿要好给和睦说的一句话,

还在用Lisview?RecyclerView都已经出来一年多了!

增添头布局和步伐:

设倘使用过RecyclerView的价值评估我们都领悟,那么些东西不像ListView那样直接能够

  • addHeaderView()或addFooterView(),removeHeaderView(),removeFooterView()所今后天就进去大家的核心,一千人就有1000个哈姆雷特,给RecyclerView增加头的艺术各有各的不二法门:就自笔者最近所见:基本相仿正是三种:
  • 上面用多个笔直的LinearLayout 里面动态的充分要么移除l
  • 依傍ListView的加多头的秘技,尽管是这种将在去看ListView的源码了,可是笔者认为这种拉长方式不是非常好,只是个体提出,因为您还得去重写recyclerview,认为依然稍稍的的有嗲麻烦
  • 其三种,也是自身接到作者要写的这一种装饰者形式加多头,给那一个指标额外的加码效果:一不开心就上代码:

/** * Created by fx on 2017/6/29. * 采用装饰着模式进行封装头部和尾部: */public class HeaderAndFooterWrapper<k> extends RecyclerView.Adapter<BaseViewHolder> { private static final int BASE_ITEM_TYPE_HEADER = 100000; private static final int BASE_ITEM_TYPE_FOOTER = 200000; private SparseArray<View> mHeaderViews = new SparseArray<>(); private SparseArray<View> mFootViews = new SparseArray<>(); private BaseAdapter<k> mInnerAdapter; private static final int M_DEFAULT_NUMBER = -1; private static final String TAG = "HeaderAndFooterWrapper"; //将我们自己的adapter 传进去: public HeaderAndFooterWrapper(BaseAdapter<k> adapter) { mInnerAdapter = adapter; } @Override public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { BaseViewHolder holder; if (mHeaderViews.get != null) { holder = BaseViewHolder.creatBaseViewHolder(mHeaderViews.get); return holder; } else if (mFootViews.get != null) { holder = BaseViewHolder.creatBaseViewHolder(mFootViews.get); return holder; } return mInnerAdapter.onCreateViewHolder(parent, viewType); } @Override public void onBindViewHolder(BaseViewHolder viewHolder, int position) { if (isHeaderViewPos) { return; } if (isFooterViewPos) { return; } mInnerAdapter.onBindViewHolder(viewHolder, position - getHeadersCount; } @Override public int getItemViewType(int position) { if (isHeaderViewPos) { return mHeaderViews.keyAt; } else if (isFooterViewPos) { return mFootViews.keyAt(position - getHeadersCount() - getRealItemCount; } return mInnerAdapter.getItemViewType(position - getHeadersCount; } private int getRealItemCount() { return mInnerAdapter.getItemCount(); } @Override public int getItemCount() { return getHeadersCount() + getFootersCount() + getRealItemCount(); } private boolean isHeaderViewPos(int position) { return position < getHeadersCount(); } private boolean isFooterViewPos(int position) { return position >= getHeadersCount() + getRealItemCount(); } //add Headers 不重复添加头布局: public void addHeaderView(View view) { int i = mHeaderViews.indexOfValue; if (M_DEFAULT_NUMBER == i) { mHeaderViews.put(mHeaderViews.size() + BASE_ITEM_TYPE_HEADER, view); } } public void addFootView(View view) { int i = mFootViews.indexOfValue; if (M_DEFAULT_NUMBER == i) { mFootViews.put(mFootViews.size() + BASE_ITEM_TYPE_FOOTER, view); } } public int getHeadersCount() { return mHeaderViews.size(); } public int getFootersCount() { return mFootViews.size(); } //针对网格布局: @Override public void onAttachedToRecyclerView(RecyclerView recyclerView) { mInnerAdapter.onAttachedToRecyclerView(recyclerView); final RecyclerView.LayoutManager manager = recyclerView.getLayoutManager(); if (manager instanceof GridLayoutManager) { ((GridLayoutManager) manager).setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { //如果是头布局或者是脚布局返回为1; int itemViewType = getItemViewType; if (mHeaderViews.get(itemViewType) != null || mFootViews.get(itemViewType) != null) { return ((GridLayoutManager) manager).getSpanCount(); } return 1; } }); } } //针对流式布局 @Override public void onViewAttachedToWindow(BaseViewHolder holder) { mInnerAdapter.onViewAttachedToWindow; int layoutPosition = holder.getLayoutPosition(); if (isHeaderViewPos(layoutPosition) || isFooterViewPos(layoutPosition)) { ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams(); if (layoutParams != null) { if (layoutParams instanceof StaggeredGridLayoutManager.LayoutParams) { StaggeredGridLayoutManager.LayoutParams params = (StaggeredGridLayoutManager.LayoutParams) layoutParams; //占领全部空间; params.setFullSpan; } } } } //remover header; public boolean removedHeader(View view) { int i = mHeaderViews.indexOfValue; if (i == M_DEFAULT_NUMBER ) { return false; } mHeaderViews.removeAt; notifyItemRemoved; return true; } //remover footer public boolean removedFooter(View view) { int i = mFootViews.indexOfValue; if (i == M_DEFAULT_NUMBER ) { return false; } mFootViews.removeAt; notifyItemRemoved; return true; } //remover all footerview; public boolean removerAllFooterView() { if (mFootViews.size { mFootViews.clear(); notifyDataSetChanged(); return true; } return false; } //remover all footerview; public boolean removerAllHeaderView() { if (mHeaderViews.size { mHeaderViews.clear(); notifyDataSetChanged(); return true; } return false; }}

在Activity里面一向那样使用

  • 添加头

ComAdapter comAdapter = new ComAdapter(C.getList; View view = mInflate.inflate(R.layout.header_view, (ViewGroup) mRecyView.getParent; HeaderAndFooterWrapper<String> emptyViewAdapter = new HeaderAndFooterWrapper<String>(comAdapter); emptyViewAdapter.addHeaderView; emptyViewAdapter.addFootView; mRecyView.setAdapter(emptyViewAdapter);///new HeaderAndFooterWrapper() 将当前的comAdapter 传入进去, 可以添加多个头布局和脚布局: 
  • 移移除单个头布局和单个脚布局
  • removedHeader
  • removedFooter
  • 移除全部的头布局和脚布局
  • removerAllHeaderView
  • removerAllFooterView

到底写完了,是否深感用起来非常粗大略,像在此以前的ListView 一样的
直接能够增添头,移除头
增添脚布局,移除脚布局;由于时间有限未有录gif视屏,前期一定补上,
废话也就非常少说了,若是大家感觉自个儿写的勉强能够,就抬起手给点个赞呗,假若有越来越好的仍旧认为写的有题目标应接提问和干扰感谢大家;

趁着青春还能够蹦跶的时候赶紧多蹦跶下,蹦跶的岁月能有多短时间就多短时间,向小强同样的宁死不屈的活着,做一个风吹不倒,雨淋不湿,雷劈不着,上能端果酒,下能进厨房的
合格90后;

想必大家多或多或少的触发过还是打听过RecyclerView,为何未有用起来,原因大致如下?

近期平素在忙一个合营社的类别因而直接感觉抽不开身,只是以为,不过事实………预计对和煦太放松了,一如既往就想去写几篇关于RecyclerView的小说不过在百度上一搜一大把
,马上一点心态都尚未,外人已经早已造好轮子了,你还去浪费时间和阅历,然则不甘心啊,为什么旁人就能够写出那般好的代码,而自个儿就十三分了,真的是旁人水平比本身高非常多要么人家比小编更是用心了,相当多一片段开辟者估算心态跟自个儿估算大致,直接复制copy就好了,重视一下库,还操那心干嘛,闲的,先把效果完结再说,可是笔者要么很相信确实的开拓者仍旧想制作一套属于自个儿的代码,敲完事后和copy之后的认为到确实是不等同的,也许敲完事后才具领略外人写代码的意图,说了那般多对不胜枚进士的话以为是废话
,我恐怕本人,就像自身第一篇写的均等简书

ListView小编用的非常好的,为啥要换RecyclerView?

不想做三个完全的伸手党;全部笔者调节那篇小说笔者不能够不写出来:

必发365游戏官方网址 2540abec6b0e297122.jpg

在此地照旧分几步去写:选拔总分总的情势,那样看起来结构跟加清晰:在这里小编插入一条总的结构图,那个组织图也是作者今天要周全的事物,假若有年轻人伴想和自身一块儿来造轮子
其中基本三月经到位了半数以上,其余的还在宏观之中,非常招待,终究营造一套属于自身的用起来找bug依旧快非常多啊;哈哈哈

ListView稳固,熟谙,还掌握多数开源库,特其他好用!

必发365游戏官方网址 3RecyClerView的分水线绘制(ItemDe.png

RecyclerView无法增加尾部,ListView能!

RecyclerView的由来:

说到RecyclerView推断是假若是Android开荒者未有二个不熟知的,安卓5.0然后将以前的列表控件替换,比起从前的ListVie\w
谷歌老爹强制行使了ViewHolder来缓存View,比起ListView真的是很用,最近现行反革命的主流app都会有列表结构的,所以这些事物不仅仅我们要简明的会用,最棒是能能用的很好,基本的安顿作者就十分少说了,哈哈
估摸大家比我们越来越的灵性,配置这么轻巧的作业对你们so easy;

RecyclerView

RecyclerView的结缘结构:

提起她不的不关乎他的五虎少将

必发365游戏官方网址 4viewholder.png

  • RecyclerView.LayoutManager 肩负Item视图的布局的来得管理
  • RecyclerView.ItemDecoration
    给各样Item视图增多子View,举个例子能够举办画分隔线之类
  • RecyclerView.ItemAnimator 担当处理数据增进或然去除时候的卡通片效果
  • RecyclerView.Adapter 为每一种Item创制视图
  • RecyclerView.ViewHolder
    承载Item视图的子布局基本上行开拓都以环绕这几点去写,五虎中校非同平日:哓哓不停终于把上边的写完了,未来终于到了核心,坐直了,睁大眼睛了.嗯嗯嗯;正式封装了

在Andorid
5.0出去不久,小编就曾经写过RecyclerView的归纳介绍以及核心使用,不打听的能够看看ListView升级版RecyclerView,通晓过的同学可以忽略,并往下看。

RecyclerView的ViewHolder封装:

  • 未封装以前的的代码:

public class ComAdapter extends RecyclerView.Adapter<ComAdapter.ComViewHolder> { private List<String> mList; public ComAdapter(List<String> mList) { this.mList = mList; } @Override public ComViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View rootViwe = LayoutInflater.from(parent.getContext.inflate(R.layout.recycler_items, parent, false); return new ComViewHolder; } @Override public void onBindViewHolder(ComViewHolder holder, int position) { holder.mTv.setText(mList.get); } @Override public int getItemCount() { return mList == null ? 0 : mList.size(); } static class ComViewHolder extends RecyclerView.ViewHolder { private TextView mTv; ComViewHolder(View itemView) { super; mTv =  itemView.findViewById; } }}

像这种类型写是还是不是很烦各种页面都要写三回重复的多寡,设置adapter holder
所以必定要优化;

  • 包装后的ViewHoldler

public class BaseViewHolder extends RecyclerView.ViewHolder { private SparseArray<View> mSparseArray; private View mConVertView; private BaseAdapter adapter; public BaseViewHolder(View itemView) { super; mSparseArray = new SparseArray<>(); mConVertView = itemView; } /** * 通过viewId获取控件 * * @param viewId * @return */ public <T extends View> T getView(int viewId) { View view = mSparseArray.get; if (view == null) { view = mConVertView.findViewById; mSparseArray.put(viewId, view); } return  view; } public BaseViewHolder setText(int viewId, String text) { TextView tv = getView; tv.setText; return this; } public BaseViewHolder setImageResource(int viewId, int resId) { ImageView view = getView; view.setImageResource; return this; } /** * 关于事件的 */ public BaseViewHolder setOnClickListener(int viewId) { View view = getView; view.setOnClickListener(new View.OnClickListener() { @Override public void onClick { adapter.getmOnItemChildClickListener().onItemChildClick(adapter, v, getAdapterPosition; return this; } public BaseViewHolder setOnTouchListener(int viewId) { View view = getView; view.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return false; } }); return this; } public BaseViewHolder setOnLongClickListener(int viewId) { View view = getView; view.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick { return false; } }); return this; } public static BaseViewHolder creatBaseViewHolder(View view) { return new BaseViewHolder; } public <T> void setAdapter(BaseAdapter adapter) { this.adapter = adapter; }}

RecyclerView最大的优势正是灵活,RecyclerView只需退换一行代码就足以改变各个分裂的布局展现排版,那或多或少对此开荒者是特别有利的!

adapter 封装:

public abstract class BaseAdapter<T> extends RecyclerView.Adapter<BaseViewHolder> { private int layoutId; private List<T> mData; //header footer private LinearLayout mHeaderLayout; private FrameLayout mEmptyLayout; private boolean mIsUseEmpty = true; private final int EMPTY_VIEW = 0x011; private final int NOMARL_VIEW = 0x012; public BaseAdapter(@Nullable int layoutId, List<T> mData) { this.layoutId = layoutId; this.mData = mData; } public BaseAdapter(@Nullable int layoutId) { this.layoutId = layoutId; } public BaseAdapter(List<T> mData) { this.mData = mData; } @Override public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { Context context = parent.getContext(); View mView = LayoutInflater.from.inflate(layoutId, parent, false); BaseViewHolder baseViewHolder = BaseViewHolder.creatBaseViewHolder;//设置监听: bindViewClickListener(mView, baseViewHolder); baseViewHolder .setAdapter; return baseViewHolder; } @Override public void onBindViewHolder(BaseViewHolder holder, int position) { convert(holder, mData.get, position); } protected abstract void convert(BaseViewHolder holder, T t, int position); //绑定事件: private void bindViewClickListener(View mView, final BaseViewHolder baseViewHolder) { mView.setOnClickListener(new View.OnClickListener() { @Override public void onClick { if (mOnItemClickListener != null) { mOnItemClickListener.onItemClick(v, baseViewHolder.getAdapterPosition; } } }); mView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick { if (OnItemLogClickListener != null) { OnItemLogClickListener.onItemLongClick(v, baseViewHolder.getAdapterPosition; } return false; } }); } @Override public int getItemCount() { if (mData == null) { throw new NullPointerException("mData is not Initialization"); } return mData.size(); } private OnItemClickListener mOnItemClickListener; private OnItemLogClickListener OnItemLogClickListener; public void setOnItemLogClickListener(BaseAdapter.OnItemLogClickListener onItemLogClickListener) { OnItemLogClickListener = onItemLogClickListener; } public interface OnItemClickListener { void onItemClick(View view, int position); } public interface OnItemLogClickListener { boolean onItemLongClick(View view, int position); } public void setOnItemClickListener(OnItemClickListener onItemClickListener) { this.mOnItemClickListener = onItemClickListener; } private OnItemChildClickListener mOnItemChildClickListener; public void setmOnItemChildClickListener(OnItemChildClickListener mOnItemChildClickListener) { this.mOnItemChildClickListener = mOnItemChildClickListener; } public OnItemChildClickListener getmOnItemChildClickListener() { return mOnItemChildClickListener; } public interface OnItemChildClickListener<T> { void onItemChildClick(BaseAdapter<T> adapter, View view, int position); }}

选拔谷歌(Google)推举的SparseArray来取代Map key是int
类型同期内部也卷入了item的子控件的点击,长按 事件 ,adapter
里面一贯行使BaseViewHolde 最终的写adapter 就是这么的

public class ComAdapter extends BaseAdapter<String> { protected ComAdapter(@Nullable int layoutId, List<String> mData) { super(layoutId, mData); } public ComAdapter(@Nullable int layoutId) { super; } public ComAdapter(List<String> mData) { super(R.layout.manactivity_items_layout, mData); } @Override protected void convert(BaseViewHolder holder, String s, int position) { holder.setText(R.id.m_tv_left, s).setOnClickListener(R.id.m_tv_left); }}

BaseViewHolder封装了有个别常用的办法 setText ,setCheck 等等…..return
this 直接就足以链式调用,//设置点击事件:就是那般轻巧:

 ComAdapter comAdapter = new ComAdapter(C.getList; mRecyView.setAdapter(comAdapter); comAdapter.setOnItemClickListener(new BaseAdapter.OnItemClickListener() { @Override public void onItemClick(View view, int position) { Toast.makeText(OnitemsOnclickActivity.this, "我是items我被点击了" + position, Toast.LENGTH_SHORT).show; comAdapter.setmOnItemChildClickListener(new BaseAdapter.OnItemChildClickListener() { @Override public void onItemChildClick(BaseAdapter adapter, View view, int position) { Toast.makeText(OnitemsOnclickActivity.this, "我是items子控件的我被点击了" + position, Toast.LENGTH_SHORT).show; comAdapter.setOnItemLogClickListener(new BaseAdapter.OnItemLogClickListener() { @Override public boolean onItemLongClick(View view, int position) { Toast.makeText(OnitemsOnclickActivity.this, "我是items的我被长按了" + position, Toast.LENGTH_SHORT).show(); return false; } });

瞩目了 好些个个人喜还好onBindViewHolder
里面开头化点击事件,那样实在是真的很耗质量的,每便设置数据的数额的时候都要把监听设置三遍,放在那其间根本是平价拿position
,而如若身处onCreateViewHolder
他也就能够只开始化贰次,从质量上的话是否优化点,从代码上是还是不是更加的优雅点以后设置点击事件的时候,只要求几行代码就可以解决了,

 @Override protected void convert(BaseViewHolder holder, String s, int position) { holder.setText(R.id.m_tv_left, s).setOnClickListener(R.id.m_tv_left); }

直白向后. 特别便于,开荒速度必然会越加便捷:

写了那样多,认为是肾都要掏空了,咬咬牙写完它,代码是人敲出来的
,如何尤其便捷的敲出好代码,将要思量稍微放的空一些,敲的是考虑,可能不是最棒可是是自己封装,

上述:只是轻松针对一些常用的包裹些,后续的还应该有添加头和上拉加载
像最顶部那张图一律 小编一贯会把她写完
,最终写的不佳愿意包容……..最终向我们推荐一下那RecyclerViewgithub

RecyclerView.Adapter,比BaseAdapter做了更加好的包装,把BaseAdapter的getView方法拆分成onCreateViewHolder方法和onBindViewHolder方法,强制需求创立ViewHolder,这样的补益便是制止了初学者写品质不好的代码

在实战中大家会遇见哪些难点?

get到上面包车型客车本领就能够在使用昂CoracyclerView的锦绣前程上通行了!

累加分水线

增添点按效果与利益

列表动画

变动有些数据保持近日地方

增添底部尾巴部分

列表分组

种种功效集成Demo

更加灵敏的RecyclerView

累加分水线

必发365游戏官方网址,RecyclerViewrecyclerView=(RecyclerView)
findViewById(R.id.recyclerview);

recyclerView.addItemDecoration(new
HorizontalDividerItemDecoration.Builder(this)

 .color(Color.RED)

 .sizeResId(R.dimen.divider)

.marginResId(R.dimen.leftmargin,R.dimen.rightmargin)

.build());

//通过以下方式增添分水岭mRecyclerView.addItemDecoration();

HorizontalDividerItemDecoration要求三番两次RecyclerView.ItemDecoration这么些抽象类达成部分方法
。但是自己倍感过于劳苦,所以本人想开的是:

直接在item_view里面尾部自身增多一根线布局,那样就无需重写了,何况那样还也可能有个好处就是,如若条分缕析的同学会开掘,增多分水岭,最终贰个item上面不会有分水岭,分明当数据量不足三个荧屏的时候显得很猝然,不过在item_view上面加多一个线的布局则不会并发这种气象

增加点按职能

RecyclerView直接在item_view里面配置就能够selector就可以。

动画

二个好的客商体验正是要有操作动画的交接,并非猛烈的基础代谢列表。

引入多个RecyclerView的动画库(recyclerview-animators)

RecyclerView自带增多、删除动画,而ListView则需增加额外的代码才具贯彻。

去除调用RecyclerView的adapter的notifyItemRemoved

充分调用RecyclerView的adapter的notifyItemInserted

聊起adapter我们就来说说RecyclerView.Adapter和BaseAdapter比较,额外提供了须臾间那一个主意:

//
数据产生了改动,那调用那么些办法,传入改造目的的义务。publicfinalvoidnotifyItemChanged(intposition);//
能够刷新从positionStart早先itemCount数量的item了publicfinalvoidnotifyItemRangeChanged(intpositionStart,intitemCount);//
增加,传入对象的职位。publicfinalvoidnotifyItemInserted(intposition);//
删除,传入对象的岗位。publicfinalvoidnotifyItemRemoved(intposition);//
对象从fromPosition移动到toPositionpublicfinalvoidnotifyItemMoved(intfromPosition,inttoPosition);//批量增加publicfinalvoidnotifyItemRangeInserted(intpositionStart,intitemCount);//批量删除publicfinalvoidnotifyItemRangeRemoved(intpositionStart,intitemCount);

改换列表有些布局意并且保持近些日子岗位

这种须要是分布存在的,正是改造列表某贰个item数据,然后刷新列表,倘诺是ListView刷新后则会回去最顶端,而RecyclerView相同的操作可是原本滑动的职位不改变。

种种建设方案的RecyclerView的Adapter

BaseRecyclerViewAdapterHelper

必发365游戏官方网址 5

职能展示

布局更加灵敏的RecyclerView

twoway-view打包了RecyclerView常用艺术,如click等等,以及帮衬了越来越多分化的布局,使得RecyclerView使用起来更简便易行!

越来越灵敏的丰裕分水线

分水岭使用请参谋 以下链接:

https://github.com/yqritc/RecyclerView-FlexibleDivider

一对文字引用了:陈宇明

参照链接:http://www.jianshu.com/p/a92955be0a3e

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*
*
Website