RecyclerView多item布局实现

第一家公司做外包,做过不少电商项目,首页设计基本都是这个样
从上至下分别一个轮播图框,一个横向滑动的view用来展示一些特殊的列表,几个快捷菜单,和一个显示商品的列表。
实际应用里截图:

 

 

这里就用一个基本的例子来实现如何RecyclerView怎么进行多item布局。

先看效果图:

 

 

 

首先,轮播图的bean,横向List的bean,和正常list的bean肯定不同,而adapter只有一个与一个数组绑定,所以三种bean要可以是统一类型的bean,所以我定义了一个三种bean的父类bean就叫它ExampleBaseBean

public class ExampleBaseBean {

private int viewType;

public int getViewType() {
return viewType;
}

public void setViewType(int viewType) {
this.viewType = viewType;
}
}
如代码所示,这个BaseBean主要作用就是提供一个int类型的vieType的对象用来区分不同类型的bean。

有了BaseBean,接下来就是三种bean了。

public class TitleBean extends ExampleBaseBean {
//轮播bean,为了方便叫titleBean
private List<String> titles;//轮播的数据源一般都为数组。

public List<String> getTitles() {
return titles;
}

public void setTitles(List<String> titles) {
this.titles = titles;
}
}

public class BodyBean extends ExampleBaseBean {
//中间横向滑动的bean ,通常都有图片展示,这里用本地图片展示
private List<Integer> res;

public List<Integer> getRes() {
return res;
}

public void setRes(List<Integer> res) {
this.res = res;
}
}
public class FootBean extends ExampleBaseBean {
//正常列表的bean
private String str;

public FootBean(String str) {
this.str = str;
}

public String getStr() {
return str;
}

}
三种bean定义完,该着手adapter了。

 

public class ExampleAdapter extends RecyclerView.Adapter {

public final static int TITLE = 1001;//标题的viewType
public final static int BODY = 1002;//横向列表的viewType
public final static int FOOT = 1003;//正常列表的viewType

private List<ExampleBaseBean> mlist;//adapter的数据源
private Context context;
private LayoutInflater inflater;


public ExampleAdapter(List<ExampleBaseBean> mlist) {
this.mlist = mlist;
}
首先在这个adapter里将会用到viewtype写成静态常量,方便外面统一。

先写三种bean对应的ViewHolder:

private class TitleHolder extends RecyclerView.ViewHolder {

ViewPager vp;

public TitleHolder(View itemView) {
super(itemView);
vp = itemView.findViewById(R.id.vp);
}
}

private class BodyHolder extends RecyclerView.ViewHolder {

RecyclerView rv;

public BodyHolder(View itemView) {
super(itemView);
rv = itemView.findViewById(R.id.rv);
}
}

private class FootHolder extends RecyclerView.ViewHolder {

TextView tv_foot;

public FootHolder(View itemView) {
super(itemView);
tv_foot = itemView.findViewById(R.id.tv_foot);
}
}
三种ViewHolder写完了,然后就是复写RecyclerView.Adapter的getItemViewType方法来控制它返回给onCreateViewHolder的viewType:

@Override
public int getItemViewType(int position) {
if (mlist.size() > 0) {
return mlist.get(position).getViewType();
}
return super.getItemViewType(position);
}

然后就是adapter的主要方法onCreateViewHolder方法:

@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if (context == null)
context = parent.getContext();
if (inflater == null)
inflater = LayoutInflater.from(context);
View view;
switch (viewType) {
case TITLE:
view = inflater.inflate(R.layout.listitem_title, parent, false);
return new TitleHolder(view);
case BODY:
view = inflater.inflate(R.layout.listitem_body, parent, false);
return new BodyHolder(view);
case FOOT:
view = inflater.inflate(R.layout.listitem_foot, parent, false);
return new FootHolder(view);
}
return null;
}
根据onCreateViewHolder方法传来的viewType进行判断然后返回对应item布局的ViewHolder。

ViewHolder会被传到onBindViewHolder方法,接下来就只再要实现onBindViewHolder里就OK了。

@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if (holder instanceof TitleHolder) {
TitleBean titleBean = (TitleBean) mlist.get(position);
((TitleHolder) holder).vp.setAdapter(new PagerAdapter(titleBean.getTitles()));
}

if (holder instanceof BodyHolder) {
BodyBean bodyBean = (BodyBean) mlist.get(position);
((BodyHolder) holder).rv.setLayoutManager(new LinearLayoutManager(context, LinearLayout.HORIZONTAL, false));
((BodyHolder) holder).rv.setAdapter(new BodyAdapter(bodyBean.getRes()));
}

if (holder instanceof FootHolder) {
FootBean footBean = (FootBean) mlist.get(position);
((FootHolder) holder).tv_foot.setText(footBean.getStr());
}
}
这里的viewPager的adapter我图省事直接写成内部类了

private class PagerAdapter extends android.support.v4.view.PagerAdapter {

List<String> stringList;

public PagerAdapter(List<String> stringList) {
this.stringList = stringList;
}

@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
ViewPager.LayoutParams params = new ViewPager.LayoutParams();
params.width = ViewPager.LayoutParams.WRAP_CONTENT;
params.height = ViewPager.LayoutParams.WRAP_CONTENT;
params.gravity = Gravity.CENTER;
TextView textView = new TextView(container.getContext());
textView.setText(stringList.get(position));
textView.setTextSize(30);
textView.setTextColor(Color.parseColor("#333333"));
textView.setLayoutParams(params);
container.addView(textView);
return textView;
}

@Override
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
container.removeView((View) object);
}

@Override
public int getCount() {
return stringList.size();
}

@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view == object;
}
}
还有一个Body的adapter就是平时展示一种数据的adapter,这里也贴一下。

public class BodyAdapter extends RecyclerView.Adapter {

private List<Integer> res;

public BodyAdapter(List<Integer> res) {
this.res = res;
}

@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.listitem_body_img, parent, false);
return new ImgHolder(view);
}

@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if (holder instanceof ImgHolder) {
((ImgHolder) holder).iv.setImageResource(res.get(position));
}
}

private class ImgHolder extends RecyclerView.ViewHolder {

ImageView iv;

public ImgHolder(View itemView) {
super(itemView);
iv = itemView.findViewById(R.id.iv);
}
}

@Override
public int getItemCount() {
return res.size();
}
}
还有就是Acitivy里模拟数据的添加代码:

public class ExampleActivity extends AppCompatActivity {

private ExampleAdapter adapter;
private List<ExampleBaseBean> mlist = new ArrayList<>();
private RecyclerView rv;
private Context context;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_example);
context = this;
rv = findViewById(R.id.rv);
initTitle();
initBody();
initFoot();
initAdapter();
}

private void initFoot() {
for (int i = 0; i < 10; i++) {
FootBean footBean=new FootBean("foot:"+i);
footBean.setViewType(ExampleAdapter.FOOT);//正常列表
mlist.add(footBean);
}
}

private void initBody() {
List<Integer> res = new ArrayList<>(6);
res.add(R.mipmap.pic1);
res.add(R.mipmap.pic2);
res.add(R.mipmap.pic3);
res.add(R.mipmap.pic4);
res.add(R.mipmap.pic5);
res.add(R.mipmap.pic6);
BodyBean bodyBean = new BodyBean();
bodyBean.setRes(res);
bodyBean.setViewType(ExampleAdapter.BODY);//设置横向列表的类型
mlist.add(bodyBean);
}

private void initTitle() {
List<String> titles = new ArrayList<>(5);
for (int i = 0; i < 5; i++) {
titles.add(new StringBuilder("标题").append(i).toString());
}
TitleBean titleBean = new TitleBean();
titleBean.setTitles(titles);
titleBean.setViewType(ExampleAdapter.TITLE);//设置为轮播类型
mlist.add(titleBean);
}

private void initAdapter() {
if (adapter == null) {
adapter = new ExampleAdapter(mlist);
rv.setLayoutManager(new LinearLayoutManager(context));
rv.setAdapter(adapter);
} else {
adapter.notifyDataSetChanged();
}
}

}

Item的xml布局也极其简单都是只有一个控件,就不贴了。
---------------------
作者:sumaniru
来源:CSDN
原文:https://blog.csdn.net/u012604975/article/details/80780164
版权声明:本文为博主原创文章,转载请附上博文链接!

posted @ 2019-01-28 09:53  天涯海角路  阅读(238)  评论(0)    收藏  举报