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布局也极其简单都是只有一个控件,就不贴了。

原文地址:https://www.cnblogs.com/xgjblog/p/14081349.html