wordpress开通多站点好处,网站建设388,网站建设学习资料,seo网站推广软件 快排目录前言基础使用分隔线点击监听搭配CardView更丰富的条目增删条目快速添加视图让RecyclerView支持复杂视图最后前言RecyclerView在Android界面开发当中是很重要的, 那掌握它也是很必要的. 但是有些时候会觉得它很厚重, 这里就从RecyclerView的基础一直说到扩展, 让你把Recycle…目录前言基础使用分隔线点击监听搭配CardView更丰富的条目增删条目快速添加视图让RecyclerView支持复杂视图最后前言RecyclerView在Android界面开发当中是很重要的, 那掌握它也是很必要的. 但是有些时候会觉得它很厚重, 这里就从RecyclerView的基础一直说到扩展, 让你把RecyclerView学薄了.这篇文章融合了自己原来的多篇文章, 并进行了修正和改进, 而且添加了很多很有趣的内容.本文需要20分钟以上的阅读时间, 请合理安排.多图预警, 转载请注明出处!基础使用要使用RecyclerView在Android Studio 2.x(以下简称AS), 要这样:compile com.android.support:cardview-v7:25.3.1compile com.android.support:recyclerview-v7:25.3.1到了AS 3.x, 要这样:implementation com.android.support:cardview-v7:26.1.0implementation com.android.support:recyclerview-v7:26.1.0之后在布局文件中写入如下代码就引入了RecyclerView了.android:idid/rv_mainandroid:layout_widthmatch_parentandroid:layout_heightmatch_parentandroid:scrollbarsvertical /布局类效果LinearLayoutManager以垂直或水平滚动列表方式显示项目GridLayoutManager在网格中显示项目StaggeredGridLayoutManager在分散对齐网格中显示项目mRvMain (RecyclerView) findViewById(R.id.rv_main);// 设置布局LinearLayoutManager linearLayoutManager new LinearLayoutManager(this);mRvMain.setLayoutManager(linearLayoutManager);最关键的还是适配器的撰写. 但是理解起来不是很难, 你只要将ListView的适配器写法带入理解就好. 这里把全部代码贴出来, 因为后面要在这个基础上不断扩充.public class MyRVAdapter2 extends RecyclerView.Adapter {private final LayoutInflater mLayoutInflater;private final Context mContext;private final ArrayList mData;public MyRVAdapter2(Context context) {mLayoutInflater LayoutInflater.from(context);mContext context;mData new ArrayList();for (int i 0; i 40; i) {mData.add(hello i);}}Overridepublic MyRVAdapter2.MyTVHolder onCreateViewHolder(ViewGroup parent, int viewType) {return new MyRVAdapter2.MyTVHolder(mLayoutInflater.inflate(R.layout.rv_txt_item, parent, false));}Overridepublic void onBindViewHolder(final MyRVAdapter2.MyTVHolder holder, int pos) {holder.mTextView.setText(mData.get(pos));}Overridepublic int getItemCount() {return mData null ? 0 : mData.size();}class MyTVHolder extends RecyclerView.ViewHolder {TextView mTextView;MyTVHolder(View itemView) {super(itemView);mTextView (TextView) itemView.findViewById(R.id.tv_txt);}}}然后写个最基础的TextView条目. 让它跑起来看看效果.android:layout_widthmatch_parentandroid:layout_heightwrap_contentandroid:orientationhorizontalandroid:idid/tv_txtandroid:layout_widthmatch_parentandroid:layout_heightwrap_contentandroid:gravitycenter_horizontalandroid:paddingdimen/eight_dpandroid:textstring/tmpandroid:textSizedimen/thirty_sp /分隔线前面的部分已经是基础的RecyclerView使用了. 那比起ListView是不是没有了分隔线. 这里上一个简单好用的开源库RecyclerView-FlexibleDivider.引入:implementation com.yqritc:recyclerview-flexibledivider:1.4.0使用:mRvMain.addItemDecoration(new HorizontalDividerItemDecoration.Builder(this).build());看效果就达到了吧.觉得不好看, 还可以自定义, 更多写法可以参见文档内容.mRvMain.addItemDecoration(new HorizontalDividerItemDecoration.Builder(this).color(Color.BLUE).sizeResId(R.dimen.two_dp).marginResId(R.dimen.eight_dp, R.dimen.eight_dp).build());而且而且, 竖着的分隔线也大丈夫哦.GridLayoutManager gridLayoutManager new GridLayoutManager(this, 2);mRvMain.setLayoutManager(gridLayoutManager);mRvMain.addItemDecoration(new VerticalDividerItemDecoration.Builder(this).build());点击监听再回忆一下在天国的ListView, 还有item的点击吧, 这个也要自己写.适配器中:public interface OnItemClickListener {void onItemClick(View view, int position);void onItemLongClick(View view, int position);}private MyRVAdapter2.OnItemClickListener mOnItemClickListener;public void setOnItemClickListener(MyRVAdapter2.OnItemClickListener mOnItemClickListener) {this.mOnItemClickListener mOnItemClickListener;}onBindViewHolder中设置点击监听.Overridepublic void onBindViewHolder(final MyRVAdapter2.MyTVHolder holder, int pos) {holder.mTextView.setText(mData.get(pos));if (mOnItemClickListener ! null) {holder.itemView.setOnClickListener(new View.OnClickListener() {Overridepublic void onClick(View v) {int pos holder.getLayoutPosition();mOnItemClickListener.onItemClick(holder.itemView, pos);}});holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {Overridepublic boolean onLongClick(View v) {int pos holder.getLayoutPosition();mOnItemClickListener.onItemLongClick(holder.itemView, pos);return false;}});}}使用监听:mAdapter.setOnItemClickListener(new MyRVAdapter2.OnItemClickListener() {Overridepublic void onItemClick(View view, int position) {Toast.makeText(UIUtil.getContext(), click position, Toast.LENGTH_SHORT).show();}Overridepublic void onItemLongClick(View view, int position) {Toast.makeText(UIUtil.getContext(), long click position, Toast.LENGTH_SHORT).show();}});搭配CardView是不是这个点击看着没啥感觉, 没事, 我们换上CardView再来一次.布局文件:xmlns:card_viewhttp://schemas.android.com/apk/res-autoandroid:layout_widthmatch_parentandroid:layout_heightwrap_contentandroid:layout_margindimen/eight_dpandroid:foregrounddrawable/card_foregroundcard_view:cardCornerRadiusdimen/four_dpandroid:idid/tv_txtandroid:layout_widthmatch_parentandroid:layout_heightwrap_contentandroid:gravitycenter_horizontalandroid:paddingdimen/eight_dpandroid:textstring/tmpandroid:textSizedimen/thirty_sp /给CardView加上水波纹点击特效:android:colorcolor/colorPrimary /在老版本就只能用选择器了, 其实效果也还好:android:drawabledrawable/card_foreground_selectorandroid:insetBottomdimen/four_dpandroid:insetLeftdimen/three_dpandroid:insetRightdimen/three_dpandroid:insetTopdimen/four_dp /更丰富的条目大家应该都知道TextView可以设置图标吧, 这里来看下效果图, 顺带感受下android界面设计语言的变化.android:layout_widthmatch_parentandroid:layout_heightwrap_contentandroid:orientationhorizontalandroid:idid/tv_txtandroid:layout_widthmatch_parentandroid:layout_heightwrap_contentandroid:drawableLeftmipmap/ic_launcherandroid:drawablePaddingdimen/sixteen_dpandroid:drawableStartmipmap/ic_launcherandroid:gravitycenter_verticalandroid:paddingdimen/eight_dpandroid:textstring/tmpandroid:textSizedimen/thirty_sp /让GridLayoutManager展示不同宽度的条目方的是4.x上的, 圆的是8.x上的, 可以看到, 变化还是很大的. 我们回正题. GridLayoutManager布局是可以设置宽度的, 不一定都是一样大的, 来看下实现.// 指定item宽度gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {Overridepublic int getSpanSize(int position) {if (position 0|| position (mAdapter.getItemCount() - 1) / 2|| position (mAdapter.getItemCount() - 1)) {return gridLayoutManager.getSpanCount();} else {return 1;}}});来看效果图, 发现我们的分隔线崩了是吧, 如果真想用这个分隔线也还是要自己动手修补修补, 改动改动, 开源库再棒也猜不到你的项目需求呀.当然了, 我还是很喜欢这个分隔线的, 我们来看看横着滚动的效果.布局文件要改动:android:layout_widthwrap_contentandroid:layout_heightmatch_parentandroid:orientationhorizontalandroid:idid/tv_txtandroid:layout_widthwrap_contentandroid:layout_heightmatch_parentandroid:gravitycenter_verticalandroid:textstring/tmpandroid:textSizedimen/thirty_sp /gridLayoutManager.setOrientation(GridLayoutManager.HORIZONTAL);展示不同布局之前变化宽度其实还是相同条目, 现在要展示不同条目:写一个图的条目:android:layout_widthmatch_parentandroid:layout_heightwrap_contentandroid:paddingdimen/eight_dpandroid:idid/iv_imgandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:layout_centerInParenttrueandroid:classlazyload srchttps://img-blog.csdnimg.cn/2022010702381440793.png data-originalmipmap/ic_launcher /public enum ITEM_TYPE {ITEM_TYPE_IMAGE,ITEM_TYPE_TEXT}这里多了判断条目类型, 还要注意返回值的变化, 用了更基类的RecyclerView.ViewHolder.Overridepublic RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {if (viewType ITEM_TYPE.ITEM_TYPE_IMAGE.ordinal()) {return new MyRVAdapter2.MyIVHolder(mLayoutInflater.inflate(R.layout.rv_img_item, parent, false));} else {return new MyRVAdapter2.MyTVHolder(mLayoutInflater.inflate(R.layout.rv_txt_item, parent, false));}}类继承上面也要变成RecyclerView.ViewHolder, 这些都是要对应的.extends RecyclerView.Adapter当然了, holder也是不能少的.public class MyIVHolder extends RecyclerView.ViewHolder {ImageView mImageView;MyIVHolder(View view) {super(view);mImageView (ImageView) view.findViewById(R.id.iv_img);}}Overridepublic void onBindViewHolder(final RecyclerView.ViewHolder holder, int pos) {if (holder instanceof MyRVAdapter2.MyTVHolder) {((MyRVAdapter2.MyTVHolder) holder).mTextView.setText(mData.get(pos));} else if (holder instanceof MyRVAdapter2.MyIVHolder) {((MyRVAdapter2.MyIVHolder) holder).mImageView.setImageDrawable(UIUtil.getDrawable(R.mipmap.ic_launcher));}// 点击监听...}顺带的, 我们把之前放宽的条目变成不同的视图, 也就是对应起来:Overridepublic int getItemViewType(int position) {if (position 0|| position (getItemCount() - 1) / 2|| position (getItemCount() - 1)) {return ITEM_TYPE.ITEM_TYPE_IMAGE.ordinal();} else {return ITEM_TYPE.ITEM_TYPE_TEXT.ordinal();}}看看效果:它还能继续地复杂, 试试瀑布流StaggeredGridLayoutManager:xmlns:card_viewhttp://schemas.android.com/apk/res-autoandroid:layout_widthmatch_parentandroid:layout_heightwrap_contentandroid:layout_margindimen/eight_dpcard_view:cardCornerRadiusdimen/four_dpandroid:layout_widthmatch_parentandroid:layout_heightwrap_contentandroid:orientationverticalandroid:idid/iv_imgandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:layout_gravitycenter_horizontalandroid:classlazyload srchttps://img-blog.csdnimg.cn/2022010702381440793.png data-originalmipmap/ic_launcher /android:idid/tv_txtandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:layout_gravitycenter_horizontalandroid:textstring/tmpandroid:textSizedimen/thirty_sp /StaggeredGridLayoutManager staggeredGridLayoutManager new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);mRvMain.setLayoutManager(staggeredGridLayoutManager);分割线又崩了, 嘿嘿, 其实用上了CardView, 分割线没什么必要再用了.增删条目现在适配器中添加增删方法:public void addData(int position) {mData.add(position, hello x);notifyItemInserted(position);}public void removeData(int position) {mData.remove(position);notifyItemRemoved(position);}再写入点击事件中, 点击增加, 长按删除:mAdapter.setOnItemClickListener(new MyRVAdapter2.OnItemClickListener() {Overridepublic void onItemClick(View view, int position) {mAdapter.addData(position);}Overridepublic void onItemLongClick(View view, int position) {mAdapter.removeData(position);}});增删条目开源库这里再上一个开源库recyclerview-animators, 可以修改增删动画, 种类也很丰富, 还能在它基础上自定义:分类动画类名CoolLandingAnimatorScaleScaleInAnimator, ScaleInTopAnimator, ScaleInBottomAnimator, ScaleInLeftAnimator, ScaleInRightAnimatorFadeFadeInAnimator, FadeInDownAnimator, FadeInUpAnimator, FadeInLeftAnimator, FadeInRightAnimatorFlipFlipInTopXAnimator, FlipInBottomXAnimator, FlipInLeftYAnimator, FlipInRightYAnimatorSlideSlideInLeftAnimator, SlideInRightAnimator, OvershootInLeftAnimator, OvershootInRightAnimator, SlideInUpAnimator, SlideInDownAnimator引入:implementation jp.wasabeef:recyclerview-animators:2.3.0使用:mRvMain.setItemAnimator(new SlideInLeftAnimator());这里给大家展示两种效果, 其它的自己尝试吧.mRvMain.setItemAnimator(new LandingAnimator());快速添加视图还有像Header, Foot这样的视图, 自己写也还是要费些功夫的, 这里推荐Android大神的库baseAdapter引入:implementation com.zhy:base-rvadapter:3.0.3添加头尾视图HeaderAndFooterWrapper mHeaderAndFooterWrapper new HeaderAndFooterWrapper(mAdapter);TextView t1 new TextView(this);t1.setText(Header 1);t1.setTextSize(30);TextView t2 new TextView(this);t2.setText(Foot 1);t2.setTextSize(30);mHeaderAndFooterWrapper.addHeaderView(t1);mHeaderAndFooterWrapper.addFootView(t2);mRvMain.setAdapter(mHeaderAndFooterWrapper);添加更多视图LoadMoreWrapper mLoadMoreWrapper new LoadMoreWrapper(mAdapter);mLoadMoreWrapper.setLoadMoreView(R.layout.rv_cv_img_txt_item);mLoadMoreWrapper.setOnLoadMoreListener(new LoadMoreWrapper.OnLoadMoreListener() {Overridepublic void onLoadMoreRequested() {}});mRvMain.setAdapter(mLoadMoreWrapper);是不是感觉特别爽, 那看看更爽的, 在不写适配器的情况下快速添加条目:final ArrayList mData new ArrayList();for (int i 0; i 40; i) {mData.add(hello i);}mRvMain.setAdapter(new CommonAdapter(this, R.layout.rv_cv_txt_item, mData) {Overrideprotected void convert(ViewHolder holder, String s, int position) {holder.setText(R.id.tv_txt, mData.get(position));}});是不是感觉省了一万个小时呢.让RecyclerView支持复杂视图每次加入新的视图都要对适配器进行比较大程度的改动, 这样是很容易出错的. 这里引入一个非常棒的开源库-AdapterDelegates, 降低下代码耦合性.引入:implementation com.hannesdorfmann:adapterdelegates3:3.0.1先不说使用细节, 来看看实现后想加入不同视图有多简单吧:ArrayList data new ArrayList();for (int i 0; i 10; i) {data.add(new B(b i));}for (int i 0; i 10; i) {data.add(new A(a i));}BaseAdapter animalAdapter new BaseAdapter(this, data);mRvMain.setAdapter(animalAdapter);是不是惊了, 也就是说, 你只要实现了A, B这些视图类, 直接新建放入数组就完事了.需要写基础适配器:public class BaseAdapter extends RecyclerView.Adapter {private AdapterDelegatesManager delegatesManager;private List items;public BaseAdapter(Activity activity, List items) {this.items items;delegatesManager new AdapterDelegatesManager();delegatesManager.addDelegate(new AAdapterDelegate(activity)).addDelegate(new BAdapterDelegate(activity));}Overridepublic int getItemViewType(int position) {return delegatesManager.getItemViewType(items, position);}Overridepublic RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {return delegatesManager.onCreateViewHolder(parent, viewType);}Overridepublic void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {delegatesManager.onBindViewHolder(items, position, holder);}Overridepublic int getItemCount() {return items.size();}}需要对每个类进行进行具体设置, 这里以A为例.public class AAdapterDelegate extends AdapterDelegate {private LayoutInflater inflater;public AAdapterDelegate(Activity activity) {inflater activity.getLayoutInflater();}Overridepublic boolean isForViewType(NonNull List items, int position) {return items.get(position) instanceof A;}NonNullOverridepublic RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent) {return new CatViewHolder(inflater.inflate(R.layout.rv_cv_img_txt_item, parent, false));}Overridepublic void onBindViewHolder(NonNull List items, int position,NonNull RecyclerView.ViewHolder holder, Nullable List payloads) {CatViewHolder vh (CatViewHolder) holder;A cat (A) items.get(position);vh.name.setText(cat.getName());}static class CatViewHolder extends RecyclerView.ViewHolder {public TextView name;public ImageView img;public CatViewHolder(View itemView) {super(itemView);name (TextView) itemView.findViewById(R.id.tv_txt);img (ImageView) itemView.findViewById(R.id.iv_img);}}}最后看完这篇应该是对RecyclerView有个大体认识了, 多练习练习就会得心应手起来了. 那还是有一点, 就像分隔线库的几次不理想表现, 具体项目要求还是要具体对待, 开源库也不是万能的. 最近不是又有什么开源项目套壳事件了嘛, 别人一开源就说自己有自主产权了真的好吗? 喜欢记得点赞或者关注我哦, 有意见或者建议评论区见~