一、RecyclerView之实现瀑布流排版 RecyclerView本身提供了三个LayoutManager的实现 LinearLayoutManager GridLayoutManager StaggeredGridLayoutManager 第一个和第二个大家比较常用,分别可以实现水平上下滑动的ListView效果和GridView的表格效果,今天我们就来 使用第三个比较陌生的StaggeredGridLayoutManager,让你实现瀑布流布局。 效果图如下: 瀑布流布局实现和LinearLayoutManager、GridLayoutManager没有太多的差别唯一差别是layoutManager和添加间 隔; //使用StaggeredGridLayoutManager StaggeredGridLayoutManager layoutManager = newStaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL); rc_test.setLayoutManager(layoutManager); rc_test.setAdapter(newMyAdapter()); //添加间隔 rc_test.addItemDecoration(newSpacesItemDecoration(16)); 间隔线SpacesItemDecoration代码如下: public class SpacesItemDecoration extends RecyclerView.ItemDecoration { private int space; public SpacesItemDecoration(int space) { this.space = space; } @ Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { outRect.left = space; outRect.right = space; outRect.bottom= space; if (parent.getChildAdapterPosition(view) == 0) { outRect.top = space; } } } 二 、RecyclerView添加Header 使用了RecyclerView会发现RecyclerView并不能像ListView那样直接通过addHeaderView的方式添加头部,所以我 们要学习如何为RecycleView添加Header; 在为RecyclerView添加Header的时候我们有如下问题需要思考: 如何为RecyclerView添加Header 如何让Header适配各种LayoutManager 对Adapter进行封装,使用更方便 1、如何为RecyclerView添加Header RecycleView添加Header是通过控制Adapter的itemType来设置的,思路就是根据不同的itemType去加载不同的布 局。 adapter代码如下: public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyHolder> { public static final int TYPE_HEADER = 0;//type为0表示为headerView public static final int TYPE_NORMAL = 1;//type为1表示为正常的item private Context context; private View headerView;//头部s public MyAdapter(Context context) { this.context = context; } publi c void setHeaderView(View view) { headerView= view; //为adapter第0个位置添加一个View并刷新适配器 notifyItemInserted(0); // notifyItemChanged(1);// // notifyItemRangeChanged(1,10);// // notifyItemRemoved(2);// // notifyItemMoved(2,5);//移 } @ Override public int getItemViewType(int position) { if (headerView== null) return TYPE_NORMAL; if (position == 0) return TYPE_HEADER; return TYPE_NORMAL; } @ Override public MyHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {if (headerView!= null && viewType == TYPE_HEADER)return newMyHolder(headerView);View view = View.inflate(viewGroup.getContext(), R.layout.item_staggered, null);return newMyHolder(view);} @Overridepublic void onBindViewHolder(MyHolder holder, final int position) {if (getItemViewType(position) == TYPE_HEADER)return;//正常item处理逻辑} @Overridepublic int getItemCount() {return 20;} public static class MyHolder extends RecyclerView.ViewHolder {public MyHolder(View itemView) {super(itemView);}}} Activity中调用如下:LinearLayoutManager layoutManager = newLinearLayoutManager(this);layoutManager.setOrientation(LinearLayoutManager.VERTICAL);rc_test.setLayoutManager(layoutManager);adapter = newMyAdapter(this);rc_test.setAdapter(adapter);View headerView = View.inflate(this,R.layout.header,null);adapter.setHeaderView(headerView);2、让Header适配各种LayoutManager上面写到为RecycleView添加Header是使用的LinearLayoutManager布局管理器,如果换成GridLayoutManager 或者StaggeredGridLayoutManager发现并不成功,所以GridLayoutManager和StaggeredGridLayoutManager要进 行单独的处理;为GridLayoutManager添加Header还需要添加如下代码:layoutManager.setSpanSizeLookup(newGridLayoutManager.SpanSizeLookup() {@Overridepublic int getSpanSize(int position) {int SpanCount = layoutManager.getSpanCount();//一个view所占单元格的个数, 默认是一个view占一个单元格return adapter.getItemViewType(position) == 0? SpanCount : 1;}});为了方便使用可以把上面放入adapter中使用,需要重写onAttachedToRecyclerView方法,代码如下:@Overridepublic void onAttachedToRecyclerView(RecyclerView recyclerView) {super.onAttachedToRecyclerView(recyclerView);RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();if(manager instanceof GridLayoutManager) {final GridLayoutManager gridManager = ((GridLayoutManager) manager);gridManager.setSpanSizeLookup(newGridLayoutManager.SpanSizeLookup() {@Overridepublic int getSpanSize(int position) {int SpanCount = gridManager.getSpanCount();//一个view所占单元格的个数, 默认是一个view占一个单元格return getItemViewType(position) == 0? SpanCount : 1;}});}} 为StaggeredGridLayoutManager添加Header需要在Adapter中重写onViewAttachedToWindow方法:@Overridepublic void onViewAttachedToWindow(MyHolder holder) {super.onViewAttachedToWindow(holder);ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();if (lp != null&& lp instanceof StaggeredGridLayoutManager.LayoutParams&& holder.getLayoutPosition() == 0) {StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp;p.setFullSpan(true);}} 3、将Adapter进行封装看到以上对RecyclewView添加Header的代码发现很多,我们不可能每一个有Header的Adapter都写这么多的代码逻辑,所以需要把上述代码逻辑进行封装到一个BaseRecycleViewAdapter中,代码如下:public abstract class BaseRecycleViewAdapter<T> extends RecyclerView.Adapter<RecyclerView.ViewHolder> {public static final int TYPE_HEADER = 0;//type为0表示为headerViewpublic static final int TYPE_NORMAL = 1;//type为1表示为正常的itemprivate ArrayList<T> mDatas = newArrayList<>();private View mHeaderView;private OnItemClickListener itemClickListener;public void setOnItemClickListener(OnItemClickListener itemClickListener) {this.itemClickListener = itemClickListener;} public void setHeaderView(View headerView) {mHeaderView= headerView;notifyItemInserted(0);} public View getHeaderView() {return mHeaderView;} public void addDatas(ArrayList<T> datas) {mDatas.addAll(datas);notifyDataSetChanged();} @Overridepublic int getItemViewType(int position) {if (mHeaderView== null) return TYPE_NORMAL;if (position == 0) return TYPE_HEADER;return TYPE_NORMAL;} @Overridepublic RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, final int viewType) {if (mHeaderView!= null && viewType == TYPE_HEADER) return newHolder(mHeaderView);return onCreate(parent, viewType);} @Overridepublic void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {if (getItemViewType(position) == TYPE_HEADER) return;final int pos = getRealPosition(viewHolder);final T data = mDatas.get(pos);onBind(viewHolder, pos, data);if (itemClickListener != null) {viewHolder.itemView.setOnClickListener(newView.OnClickListener() {@Overridepublic void onClick(View v) {itemClickListener.onItemClick(pos, data);}});}} @Overridepublic void onAttachedToRecyclerView(RecyclerView recyclerView) {super.onAttachedToRecyclerView(recyclerView);RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();if (manager instanceof GridLayoutManager) {final GridLayoutManager gridManager = ((GridLayoutManager) manager);gridManager.setSpanSizeLookup(newGridLayoutManager.SpanSizeLookup() {@Overridepublic int getSpanSize(int position) {return getItemViewType(position) == TYPE_HEADER? gridManager.getSpanCount() : 1;}});}} @Overridepublic void onViewAttachedToWindow(RecyclerView.ViewHolder holder) {super.onViewAttachedToWindow(holder);ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();if (lp != null&& lp instanceof StaggeredGridLayoutManager.LayoutParams&& holder.getLayoutPosition() == 0) {StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp;p.setFullSpan(true);}} /*** 获取item正确的position* @param holder* @return*/public int getRealPosition(RecyclerView.ViewHolder holder) {int position = holder.getLayoutPosition();return mHeaderView== null ? position : position - 1;} @Overridepublic int getItemCount() {return mHeaderView== null ? mDatas.size() : mDatas.size() + 1;} public abstract RecyclerView.ViewHolder onCreate(ViewGroup parent, final int viewType);public abstract void onBind(RecyclerView.ViewHolder viewHolder, int RealPosition, T data);public class Holder extends RecyclerView.ViewHolder {public Holder(View itemView) {super(itemView);}} /*** 处理item点击监听* @param <T>*/public interface OnItemClickListener<T> {void onItemClick(int position, T data);}} 具体集成BaseRecycleViewAdapter使用如下:public class MyAdapter2 extends BaseRecycleViewAdapter {@Overridepublic RecyclerView.ViewHolder onCreate(ViewGroup parent, int viewType) {View view = View.inflate(parent.getContext(), R.layout.item_staggered, null);return newMyHolder(view);} @Overridepublic void onBind(RecyclerView.ViewHolder viewHolder, int RealPosition, Object data) {} class MyHolder extends BaseRecycleViewAdapter.Holder {TextView text;public MyHolder(View itemView) {super(itemView);text = (TextView) itemView.findViewById(R.id.text);}}} |
RecyclerView进阶
最新推荐文章于 2021-12-26 16:57:50 发布