美文网首页Android技术知识Android开发Android开发经验谈
RecyclerView使用指南(二)—— 多种ItemLayo

RecyclerView使用指南(二)—— 多种ItemLayo

作者: 28292f4144cb | 来源:发表于2018-11-27 08:37 被阅读65次

    声明:原创作品,转载请注明出处:https://www.jianshu.com/p/7d30ba789a46

    我在上一篇文章《RecyclerView使用指南(一)—— 基本使用》中讲解了RecyclerView的最基本用法。
    这一篇,我来讲解一下多种条目布局应该如何显示。(如果没看过上一篇文章的小朋友,建议去看一下短小的上一篇文章。。。)
    没图说个**:

    • 核心思路:
    1. 针对不同的条目布局,我们创建不同的ViewHolder。
    2. Adapter需要知道在什么情况下使用什么样的布局。

    Adapter中,我们可以通过重写getItemViewType(int position)方法,根据数据源,返回不同的viewType,Adapter在onCreateViewHolder和onBindViewHolder方法中使用这个值来创建ViewHolder和绑定相应的数据。

    一、数据源为同种类型

    总上所述,我们可以写一个简单的示例代码,它的数据源都是Data类型。如下:

    package com.liuym.myapplication;
    
    import android.support.annotation.NonNull;
    import android.support.v7.widget.RecyclerView;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ImageView;
    import android.widget.TextView;
    
    import java.util.List;
    
    public class RvAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
        //条目类型
        public static final int TYPE_0 = 0;
        public static final int TYPE_1 = 1;
    
        //数据源
        private List<Data> mList;
    
        public RvAdapter(List<Data> list) {
            mList = list;
        }
    
        @NonNull
        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
            View item;
            RecyclerView.ViewHolder holder = null;
            if (viewType == TYPE_0) {
                item = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_rv_type1, viewGroup, false);
                holder = new Type0ViewHolder(item);
            }
            if (viewType == TYPE_1) {
                item = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_rv_type2, viewGroup, false);
                holder = new Type1ViewHolder(item);
            }
            return holder;
        }
    
        /**
         * 根据数据源的某一项,返回相应的布局类别
         *
         * @param position
         * @return
         */
        @Override
        public int getItemViewType(int position) {
            return mList.get(position).getType();
        }
    
        @Override
        public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
            int type = getItemViewType(i);
            Data data = mList.get(i);
            if (type == TYPE_0) {
                Type0ViewHolder holder = (Type0ViewHolder) viewHolder;
                holder.iv.setImageResource(R.drawable.ic_launcher_background);
                holder.tv.setText(data.getText());
            }
            if (type == TYPE_1) {
                Type1ViewHolder holder = (Type1ViewHolder) viewHolder;
                holder.iv.setImageResource(R.drawable.ic_launcher_background);
                holder.tv.setText(data.getText());
            }
        }
    
        @Override
        public int getItemCount() {
            return mList == null ? 0 : mList.size();
        }
    
    
        class Type0ViewHolder extends RecyclerView.ViewHolder {
            ImageView iv;
            TextView tv;
    
            public Type0ViewHolder(@NonNull View itemView) {
                super(itemView);
                iv = itemView.findViewById(R.id.iv);
                tv = itemView.findViewById(R.id.tv);
            }
        }
    
        class Type1ViewHolder extends RecyclerView.ViewHolder {
            ImageView iv;
            TextView tv;
    
            public Type1ViewHolder(@NonNull View itemView) {
                super(itemView);
                iv = itemView.findViewById(R.id.iv);
                tv = itemView.findViewById(R.id.tv);
            }
        }
    }
    

    二、数据源为不同类型

    那么,如果我们要显示不同种类型的怎么办呢?比如这个列表既包含铅笔,又包含橡皮,怎么办?
    这里,我们的数据源要包含两个类:Pencil类和Eraser类,为了将它们放到同一个列表中,我们可以让它们实现同一个接口,讲到这里,是不是有思路了呢?
    好,我们来实现这个功能!

    1. 创建一个接口:
    package com.liuym.myapplication;
    
    public interface IMultiType {
        /**
         * 返回条目类型
         *
         * @return
         */
        int getItemType();
    }
    
    1. 创建Pencil类实现IMultiType接口(Eraser类和Pencil类基本一致,只是返回的itemType不同):
    package com.liuym.myapplication;
    
    public class Pencil implements IMultiType {
        private String msg;
    
        public Pencil(String msg) {
            this.msg = msg;
        }
    
        public String getMsg() {
            return msg;
        }
    
        public void setMsg(String msg) {
            this.msg = msg;
        }
    
        @Override
        public int getItemType() {
            return RvAdapter.TYPE_PENCIL;
        }
    }
    
    1. 修改Adapter的数据源,将IMultiType的子类放入到数据源中,重写getItemViewType(int position)方法,完整代码如下:
    package com.liuym.myapplication;
    
    import android.support.annotation.NonNull;
    import android.support.v7.widget.RecyclerView;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ImageView;
    import android.widget.TextView;
    
    import java.util.List;
    
    public class RvAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
        //条目类型
        public static final int TYPE_PENCIL = 0;
        public static final int TYPE_ERASER = 1;
    
        //数据源
        private List<IMultiType> mList;
    
        public RvAdapter(List<IMultiType> list) {
            mList = list;
        }
    
        @NonNull
        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
            View item;
            RecyclerView.ViewHolder holder = null;
            if (viewType == TYPE_PENCIL) {
                item = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_rv_type1, viewGroup, false);
                holder = new PencilViewHolder(item);
            }
            if (viewType == TYPE_ERASER) {
                item = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_rv_type2, viewGroup, false);
                holder = new EraserViewHolder(item);
            }
            return holder;
        }
    
        /**
         * 根据数据源的某一项,返回相应的布局类别
         *
         * @param position
         * @return
         */
        @Override
        public int getItemViewType(int position) {
            return mList.get(position).getItemType();
        }
    
        @Override
        public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
            int type = getItemViewType(i);
            if (type == TYPE_PENCIL) {
                Pencil pencil = (Pencil) mList.get(i);
                PencilViewHolder holder = (PencilViewHolder) viewHolder;
                holder.iv.setImageResource(R.drawable.ic_launcher_background);
                holder.tv.setText(pencil.getMsg());
            }
            if (type == TYPE_ERASER) {
                Eraser eraser = (Eraser) mList.get(i);
                EraserViewHolder holder = (EraserViewHolder) viewHolder;
                holder.iv.setImageResource(R.drawable.ic_launcher_background);
                holder.tv.setText(eraser.getMsg());
            }
        }
    
        @Override
        public int getItemCount() {
            return mList == null ? 0 : mList.size();
        }
    
    
        class PencilViewHolder extends RecyclerView.ViewHolder {
            ImageView iv;
            TextView tv;
    
            public PencilViewHolder(@NonNull View itemView) {
                super(itemView);
                iv = itemView.findViewById(R.id.iv);
                tv = itemView.findViewById(R.id.tv);
            }
        }
    
        class EraserViewHolder extends RecyclerView.ViewHolder {
            ImageView iv;
            TextView tv;
    
            public EraserViewHolder(@NonNull View itemView) {
                super(itemView);
                iv = itemView.findViewById(R.id.iv);
                tv = itemView.findViewById(R.id.tv);
            }
        }
    }
    
    1. 设置数据源给Adapter,并将Adapter设置给RecyclerView
    private void initRv() {
            List<IMultiType> list = new ArrayList<>();
            for (int i = 0; i < 20; i++) {
                if (i % 2 == 0) {
                    String msg = String.format("eraser: %1s", i);
                    list.add(new Eraser(msg));
                } else {
                    String msg = String.format("pencil: %1s", i);
                    list.add(new Pencil(msg));
                }
            }
            RecyclerView recyclerView = findViewById(R.id.rv);
            RvAdapter adapter = new RvAdapter(list);
            recyclerView.setAdapter(adapter);
        }
    

    总结

    这一篇,我讲解了如何在RecyclerView中使用不同的布局,下一篇,我会讲解如何给RecyclerView添加分割线以及给Item设置点击事件。

    系列文章

    《RecyclerView使用指南(一)—— 基本使用》
    《RecyclerView使用指南(二)—— 多种ItemLayout》
    《RecyclerView使用指南(三)—— 添加分割线和点击事件》
    《RecyclerView使用指南(四)—— 使用ItemDecoration》
    《RecyclerView使用指南(五)—— 实现吸顶效果》

    相关文章

      网友评论

        本文标题:RecyclerView使用指南(二)—— 多种ItemLayo

        本文链接:https://www.haomeiwen.com/subject/mvdjqqtx.html