优化版本点击这里
RecyclerView使用也有一段时间了 他的出现是对ListView,GridView的进化,
LayoutManager负责布局Adpater负责数据处理自带缓存机制,不用开发者过多处理,更多的关注业务逻辑就行
更加灵活,但是需要开发者多多的操作相关事件,比如点击事件那就需要自定义接口,没有类似于ListView的addHaedView等方法在使用中用的多的就是有添加头部尾部 加载更多 下拉刷新(可以和系统的refreshlayout)一起使用
项目中我用的是easyRecyclerView 开源项目(自行github 挺好用) 主要是加载更多和下拉刷新实现了 添加头部尾部貌似不行 用这个LayoutManager来辅助实现 完全可以 因为EasyRecyclerView的加载更多等等解耦很好 都是Adpater来处理数据 解耦的好处 互不影响 真是其实厉害
正题
前面看到一篇博客
源地址
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的修改
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>