RecyclerView LayoutManager分析 添加头部尾部
2015-10-10 17:49
543 查看
如果图片不能显示 请点击这里
RecyclerView使用也有一段时间了 他的出现是对ListView,GridView的进化,LayoutManager负责布局
Adpater负责数据处理
自带缓存机制,不用开发者过多处理,更多的关注业务逻辑就行
更加灵活,但是需要开发者多多的操作相关事件,比如点击事件那就需要自定义接口,没有类似于ListView的addHaedView等方法
在使用中用的多的就是有添加头部尾部 加载更多 下拉刷新(可以和系统的refreshlayout)一起使用
项目中我用的是easyRecyclerView 开源项目(自行github 挺好用,功能挺全 )
正题来了
前面看到一篇博客 分析如何用LayoutManager布局管理来实现头部尾部的添加 比较方便
源地址
http://m.blog.csdn.net/blog/oushangfeng123/47435867
讲用LayoutManager来实现RecycleView的头部尾部添加,特意实现了一遍 它里面稍微分析了一下 看了一下源码 我就不分析了 看他的原帖去吧
先看个效果 都是添加了头部和尾部
主Activity代码
public class RecyclerViewMainActivity extends ActionBarActivity { private android.widget.Button bt1; private android.widget.Button bt2; private android.widget.Button bt3; private RecyclerView rcv; private GridLayoutManager gridLayoutManager; private StaggeredGridLayoutManager staggeredGridLayoutManager; List<String> lists=new ArrayList<String>(); private LinearLayoutManager linearLayoutManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_recycler_view_main); this.rcv = (RecyclerView) findViewById(R.id.rcv); this.bt3 = (Button) findViewById(R.id.bt3); this.bt2 = (Button) findViewById(R.id.bt2); this.bt1 = (Button) findViewById(R.id.bt1); bt2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { gridLayoutManager = new GridLayoutManager(RecyclerViewMainActivity.this, 2); lists.clear(); for(int i=0 ; i<20 ; i++){ lists.add("123"+i); } RecycleViewGridAdapter recycleViewAdapter = new RecycleViewGridAdapter(lists); LayoutInflater layoutInflater = getLayoutInflater(); View view = layoutInflater.inflate(R.layout.item_top, null); recycleViewAdapter.addHeadView(view); View view1 = layoutInflater.inflate(R.layout.item_foot, null); recycleViewAdapter.addFootView(view1); //如果添加了头部或者尾部 就需要做相关的SpanSize的修改 回调接口 设置layoutmanager的spanSize recycleViewAdapter.setChangeGridLayoutManager(new RecycleViewGridAdapter.ChangeGridLayoutManagerSpance() { @Override public void change(final int size, final boolean isAddHead, final boolean isAddFoot) { gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { int spanSzie = 1; if (isAddHead) { if (position == 0) { spanSzie = gridLayoutManager.getSpanCount(); } } if (isAddFoot) { if (position == size) { spanSzie = gridLayoutManager.getSpanCount(); } } return spanSzie; } }); } }); rcv.setLayoutManager(gridLayoutManager); rcv.setAdapter(recycleViewAdapter); } }); bt3.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { staggeredGridLayoutManager=new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL); lists.clear(); for(int i=0 ; i<20 ; i++){ lists.add("123"+i); } RecycleViewStageredAdapter recycleViewStageredAdapter = new RecycleViewStageredAdapter(lists); recycleViewStageredAdapter.addHeadView(R.layout.item_top); recycleViewStageredAdapter.addFootView(R.layout.item_top); rcv.setLayoutManager(staggeredGridLayoutManager); rcv.setAdapter(recycleViewStageredAdapter); } }); bt1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { linearLayoutManager=new LinearLayoutManager(RecyclerViewMainActivity.this); linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); lists.clear(); for(int i=0 ; i<20 ; i++){ lists.add("123"+i); } RecycleviewLinearAdapter recycleviewLinearAdapter=new RecycleviewLinearAdapter(lists); LayoutInflater layoutInflater = getLayoutInflater(); View view = layoutInflater.inflate(R.layout.item_top, null); recycleviewLinearAdapter.addHeadView(view); View view1 = layoutInflater.inflate(R.layout.item_foot, null); recycleviewLinearAdapter.addFootView(view1); rcv.setLayoutManager(linearLayoutManager); rcv.setAdapter(recycleviewLinearAdapter); } }); } }
然后是各个ViewHolder 整体结构图
RecycleviewLinearAdapter 代码
public class RecycleviewLinearAdapter<T> extends RecyclerView.Adapter<LinearViewHolder> { private static final int TYPE_HEADER = 0, TYPE_ITEM = 1, TYPE_FOOT = 2; public List<T> mDatas; private View headView; private View footView; private int headViewSize = 0; private int footViewSize = 0; private boolean isAddFoot = false; private boolean isAddHead = false; public RecycleviewLinearAdapter(List<T> mDatas) { this.mDatas = mDatas; } public void addHeadView(View view) { headView = view; headViewSize = 1; isAddHead = true; } public void addFootView(View view) { footView = view; footViewSize = 1; isAddFoot = true; } @Override public int getItemViewType(int position) { int type = TYPE_ITEM; if (headViewSize == 1 && position == 0) { type = TYPE_HEADER; } else if (footViewSize == 1 && position == getItemCount() - 1) { //最后一个位置 type = TYPE_FOOT; } return type; } @Override public LinearViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = null; switch (viewType) { case TYPE_HEADER: view = headView; break; case TYPE_ITEM: view = View.inflate(parent.getContext(), R.layout.item_icon, null); break; case TYPE_FOOT: view = footView; break; } return new LinearViewHolder(view); } @Override public void onBindViewHolder(LinearViewHolder holder, int position) { } @Override public int getItemCount() { return mDatas.size()+headViewSize+footViewSize; } } class LinearViewHolder extends RecyclerView.ViewHolder { public LinearViewHolder(View itemView) { super(itemView); } }
RecycleViewGridAdapter 代码
public class RecycleViewGridAdapter<T> extends RecyclerView.Adapter<MyViewHolder> { private static final int TYPE_HEADER = 0, TYPE_ITEM = 1, TYPE_FOOT = 2; public List<T> mDatas; private View headView; private View footView; private int headViewSize = 0; private int footViewSize = 0; private ChangeGridLayoutManagerSpance changeGridLayoutManager; private boolean isAddFoot=false; private boolean isAddHead=false; public interface ChangeGridLayoutManagerSpance{ public void change(int size, boolean isAddHead, boolean isAddFoot); } //提供接口给 让LayoutManager根据添加尾部 头部与否来做判断 显示头部与底部的SpanSize要在添加头部和尾部之后 public void setChangeGridLayoutManager(ChangeGridLayoutManagerSpance changeGridLayoutManager){ this.changeGridLayoutManager=changeGridLayoutManager; changeGridLayoutManager.change(getItemCount()-1,isAddHead,isAddFoot); } public RecycleViewGridAdapter(List<T> datas) { mDatas = datas; } public void addHeadView(View view) { headView = view; headViewSize = 1; isAddHead=true; } public void addFootView(View view) { footView = view; footViewSize = 1; isAddFoot=true; } @Override public int getItemViewType(int position) { int type = TYPE_ITEM; if (headViewSize==1 && position == 0) { type = TYPE_HEADER; } else if (footViewSize==1 && position == getItemCount()-1) { //最后一个位置 type = TYPE_FOOT; } return type; } @Override public MyViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { View view = null; switch (i) { case TYPE_HEADER: view = headView; break; case TYPE_ITEM: view = View.inflate(viewGroup.getContext(), R.layout.item_icon, null); break; case TYPE_FOOT: view =footView; break; } return new MyViewHolder(view); } @Override public void onBindViewHolder(MyViewHolder holder, int position) { } @Override public int getItemCount() { return mDatas.size() + headViewSize + footViewSize; } } class MyViewHolder extends RecyclerView.ViewHolder { public MyViewHolder(View itemView) { super(itemView); } }
RecycleViewStageredAdapter 代码
public class RecycleViewStageredAdapter<T> extends RecyclerView.Adapter<MyViewHolder1>{ private static final int TYPE_HEADER = 0, TYPE_ITEM = 1, TYPE_FOOT = 2; public List<T> mDatas; private int headViewid; private int headViewSize; private boolean isAddHead; private int footViewid; private int footViewSize; private boolean isAddFoot; public RecycleViewStageredAdapter(List<T> mDatas) { this.mDatas = mDatas; } public void addHeadView(int view) { headViewid = view; headViewSize = 1; isAddHead=true; } public void addFootView(int view) { footViewid = view; footViewSize = 1; isAddFoot=true; } @Override public MyViewHolder1 onCreateViewHolder(ViewGroup viewGroup, int i) { View view = null; switch (i) { case TYPE_HEADER: view = LayoutInflater.from(viewGroup.getContext()).inflate(headViewid, viewGroup, false); break; case TYPE_ITEM: view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_icon, viewGroup, false); break; case TYPE_FOOT: view = LayoutInflater.from(viewGroup.getContext()).inflate(footViewid, viewGroup, false); break; } return new MyViewHolder1(view); } @Override public void onBindViewHolder(MyViewHolder1 myViewHolder, int i) { switch (myViewHolder.getItemViewType()) { case TYPE_HEADER: // 获取cardview的布局属性,记住这里要是布局的最外层的控件的布局属性,如果是里层的会报cast错误 StaggeredGridLayoutManager.LayoutParams clp = (StaggeredGridLayoutManager.LayoutParams) myViewHolder.cardview.getLayoutParams(); // 最最关键一步,设置当前view占满列数,这样就可以占据两列实现头部了 if(clp!=null) clp.setFullSpan(true); break; case TYPE_ITEM: ViewGroup.LayoutParams layoutParams=myViewHolder.cardview.getLayoutParams(); layoutParams.height= (int) ((i%mDatas.size()+1)*20); myViewHolder.cardview.setLayoutParams(layoutParams); break; case TYPE_FOOT: // 获取cardview的布局属性,记住这里要是布局的最外层的控件的布局属性,如果是里层的会报cast错误 StaggeredGridLayoutManager.LayoutParams clp1 = (StaggeredGridLayoutManager.LayoutParams) myViewHolder.cardview.getLayoutParams(); // 最最关键一步,设置当前view占满列数,这样就可以占据两列实现头部了 clp1.setFullSpan(true); break; } } @Override public int getItemViewType(int position) { int type = TYPE_ITEM; if (headViewSize==1 && position == 0) { type = TYPE_HEADER; } else if (footViewSize==1 && position == getItemCount()-1) { //最后一个位置 type = TYPE_FOOT; } return type; } @Override public int getItemCount() { return mDatas.size()+headViewSize+footViewSize; } } class MyViewHolder1 extends RecyclerView.ViewHolder{ public CardView cardview; public MyViewHolder1(View itemView) { super(itemView); cardview = (CardView) itemView.findViewById(R.id.cv); } }
发现其实都很长不差不多太多 LinearLayoutManager没啥难点
GridLayoutManager 是要设置SpanSize每行的占位大小
StaggerLayoutManager 就是要获取StaggerLayoutManager的LayoutParams 的setFullSpan 方法来设置占位宽度
贴一贴布局代码
item
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:id="@+id/cv" > <ImageView android:id="@+id/iv_show" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@mipmap/ic_launcher" /> </android.support.v7.widget.CardView >
top
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/cv" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:cardCornerRadius="8dp" app:cardElevation="5dp" app:contentPadding="1dp" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="top" android:textSize="100dp" /> </android.support.v7.widget.CardView>
foot
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/cv" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Foot" android:textSize="100dp" /> </android.support.v7.widget.CardView>
相关文章推荐
- 学习RecyclerView和CardView
- Android RecyclerView
- 最基础的RecyclerView
- RecyclerView 使用中的几个问题
- RecyclerView入门简介
- 深入解析RecyclerView
- 个人笔记:bugs(2)
- RecyclerView 解析(一)
- MVP模式的RecyclerView案例
- Android之侧滑删除RecyclerView
- 打造RecyclerView的通用适配器
- SwipeRecyclerView
- xml文件里让recyclerview显示item布局
- Android5.0新控件——RecyclerView的使用全解
- RecyclerView上拉加载Demo
- RecyclerView组件自定义分组
- 滑动删除Item,拖拽切换Item,你想了解的都在这儿
- RecyclerView使用完全指南,是时候体验新控件了(二)
- Android RecyclerView源码学习
- HeaderView、FooterView、刷新、加载更多,支持自定义组装的RecyclerView组件