赞
踩
自从RecycleView推出后,其功能的强大让你纯粹能忘掉ListView和GridView等列表布局,因为RecycleView能够代替他们,而且使代码更加健壮,今天要说的是目前APP中最流行的布局,如下图:
图中显示的就是一个RecycleView中实现排列的布局,下面我在一个RecycleView中运用了两种布局:
下面我们看一下具体的代码实现,我先创建了两种类型的数据,OneTypeBean和TwoTypeBean,其中这两个类的成员变量不一致,将来是分别显示在两种不同的不居中的:
//第一种类型的bean
public class OneTypeBean {
private String name;
private int imageView;
private String professional;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getImageView() {
return imageView;
}
public void setImageView(int imageView) {
this.imageView = imageView;
}
public String getProfessional() {
return professional;
}
public void setProfessional(String professional) {
this.professional = professional;
}
public OneTypeBean(String name, int imageView, String professional) {
this.name = name;
this.imageView = imageView;
this.professional = professional;
}
}
//第二种类型的bean
public class TwoTypeBean {
private String title;
private int img;
public TwoTypeBean(String title, int img) {
this.title = title;
this.img = img;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getImg() {
return img;
}
public void setImg(int img) {
this.img = img;
}
}
然后模拟创建两种类型的假数据:
oneList = new ArrayList<>();
twoeList = new ArrayList<>();
for (int i = 0; i < 4; i++) {
oneList.add(new OneTypeBean("中华美食", images_1[i % 6], "独特的西北特色"));
}
for (int i = 0; i < 4; i++) {
twoeList.add(new TwoTypeBean("[ 女人装 ]", images_2[i % 9]));
}
将这两种假数据传递到RecycleView的Adapter中,因为想将两种类型的数据排放在两种不同的布局之中,所以我在Adapter定义了两个整型常量:
public static final int ONE_TYPE = 1;
public static final int TWO_TYPE = 2;
然后创建了两种数据结构分别存放每个position的类型和每个位置相对应的type:
private List<OneTypeBean> oneList;
private List<TwoTypeBean> twoList;
private List<Integer> types = new ArrayList<>();
private Map<Integer, Integer> mPosition = new HashMap<>();
public MyAdapter(Context mContext, List<OneTypeBean> oneList, List<TwoTypeBean> twoList) {
this.mContext = mContext;
this.oneList = oneList;
this.twoList = twoList;
for (int i = 0; i < oneList.size(); i++) {
types.add(ONE_TYPE);
mPosition.put(i,ONE_TYPE);
}
for (int i = 0; i < twoList.size(); i++) {
types.add(TWO_TYPE);
mPosition.put(i+oneList.size(),TWO_TYPE);
}
}
然后重写Adapter中的一个方法,返回该数据的类型常量:
@Override
public int getItemViewType(int position) {
return mPosition.get(position);
}
对于RecycleView的高效体现在它创建的ViewHolder来缓冲布局,不必为此创建,达到布局复用,减少内存的消耗和界面的卡顿,我在这里先创建了一个抽象的泛型为* *的AbstractTypeViewHolder继承RecycleView的ViewHolder;
public abstract class AbstractTypeViewHolder<T> extends RecyclerView.ViewHolder{
public AbstractTypeViewHolder(View itemView) {
super(itemView);
}
}
然后单独OneTypeViewHolder和TwoTypeViewHolder分别继承AbstractTypeViewHolder,然后写一个构造函数,绑定布局:
//第一种类型的ViewHolder
public class OneTypeViewHolder extends AbstractTypeViewHolder<OneTypeBean> {
public ImageView header;
public TextView name;
public TextView describe;
public OneTypeViewHolder(View itemView) {
super(itemView);
header = (ImageView) itemView.findViewById(R.id.iv_header);
name = (TextView)itemView.findViewById(R.id.tv_name);
describe = (TextView)itemView.findViewById(R.id.tv_describe);
}
}
//第二中类型的ViewHolder
public class TwoTypeViewHolder extends AbstractTypeViewHolder<TwoTypeBean> {
public ImageView iv_girl;
public TextView tv_describe;
public TwoTypeViewHolder(View itemView) {
super(itemView);
iv_girl = (ImageView) itemView.findViewById(R.id.iv_food);
tv_describe = (TextView)itemView.findViewById(R.id.tv_title);
}
}
将这两种ViewHolder写好后,就是将这两种进行布局复用的ViewHolder添加到我们的Adapter中,在Adapter中根据Type来创建不同的ViewHolder:
LayoutInflater inflater = LayoutInflater.from(mContext);
switch (viewType) {
case ONE_TYPE:
View viewOne = inflater.inflate(R.layout.onetype_layout, parent, false);
return new OneTypeViewHolder(viewOne);
case TWO_TYPE:
View viewTwo = inflater.inflate(R.layout.twotype_layout, parent, false);
return new TwoTypeViewHolder(viewTwo);
}
return null;
创建好ViewHolder后就给ViewHolder上面根据不断地绑定数据:position判断当前的数据Type,根据Type去给viewHolder绑定各自的数据:
switch (mPosition.get(position)) {
case ONE_TYPE:
((OneTypeViewHolder) holder).header.setBackgroundResource(oneList.get(position).getImageView());
((OneTypeViewHolder) holder).name.setText(oneList.get(position).getName());
((OneTypeViewHolder) holder).describe.setText(oneList.get(position).getProfessional());
break;
case TWO_TYPE:
int realPos2 = position - twoList.size();
((TwoTypeViewHolder)holder).iv_girl.setBackgroundResource(twoList.get(realPos2).getImg());
((TwoTypeViewHolder)holder).tv_describe.setText(twoList.get(realPos2).getTitle());
break;
}
最后,也是最重要的一点,在GridLayoutManager中设置SpanSize,根据Type返回不同的数据所占的列数,如何类型为1,返回要占据你设置显示列数的几分,相当于以你设置的列数为为分母,要返回的是分子:
GridLayoutManager gm = new GridLayoutManager(this, 2);
gm.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
switch(adapter.getItemViewType(position)){
case 1:
return 2;
case 2:
return 1;
}
return 0;
}
});
ok,就这样实现了RecycleView的两种布局,思路就是这样,如果有三个四个类型的数据相信也是照葫芦画瓢,上面的项目代码已经放在了GitHub上,点击下载,别忘记start啊
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。