RecyclerView详细介绍-----多item布局(三)

1.前言

前面两篇文章主要介绍了recyclerview的基本使用,接下来介绍复杂一点的需求。
我们之前用listview的时候肯定遇到itemType>1的时候,我们定义多套item布局,借助getItemViewType()实现多套布局。但是如果像淘宝首页,上面是listview的一个一个item,下面确是一个GridView的话,我们如何实现呢?当然之前有人会把GridView用ListView来实现,及一个Listview的item来代替GridView的两个item,只是数据集我们要自己做处理,总之很麻烦。现在有了recyclerview,这些就变得很简单。

2.实现效果

这里写图片描述
上图既有listview的列表,下方又有gridview,如何实现呢?

3.具体实现过程:

1)跟listview一样,recyclerview借助getItemViewType(int position)实现多套布局判断,然后根据itemtype实现多套布局的创建跟赋值,具体代码如下:

public class MultiItemAdapter extends RecyclerView.Adapter<MultiItemAdapter.ViewHolder> {

    public static final int ONE_TEXT_VIEW_TYPE = 0;

    public static final int TWO_TEXT_VIEW_TYPE = 1;

    public static final int GRID_VIEW_TYP = 2;

    private ArrayList<Person> data;

    private Context context;

    public MultiItemAdapter(Context context, ArrayList<Person> data) {
        this.data = data;
        this.context = context;
    }

    @Override
    public int getItemViewType(int position) {
        if (data.get(position).getType() == ONE_TEXT_VIEW_TYPE) {
            return ONE_TEXT_VIEW_TYPE;
        } else if (data.get(position).getType() == TWO_TEXT_VIEW_TYPE) {
            return TWO_TEXT_VIEW_TYPE;
        } else if (data.get(position).getType() == GRID_VIEW_TYP) {
            return GRID_VIEW_TYP;
        }else {
            return  ONE_TEXT_VIEW_TYPE;
        }
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        View itemView = null;
        switch (viewType) {
            case ONE_TEXT_VIEW_TYPE:
                itemView = LayoutInflater.from(this.context).inflate(R.layout.multi_item_one, null);
                break;
            case TWO_TEXT_VIEW_TYPE:
                itemView = LayoutInflater.from(this.context).inflate(R.layout.multi_item_two, null);
                break;
            case GRID_VIEW_TYP:
                itemView = LayoutInflater.from(this.context).inflate(R.layout.multi_item_three, null);
                break;
        }
        return new ViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        int itemViewType = getItemViewType(position);
        switch (itemViewType) {
            case ONE_TEXT_VIEW_TYPE:
                showOneTextView(holder, position);
                break;
            case TWO_TEXT_VIEW_TYPE:
                showTwoTextView(holder, position);
                break;
            case GRID_VIEW_TYP:
                showGridView(holder, position);
                break;
        }
    }

    /**
     * 赋值
     *
     * @param holder
     * @param position
     */
    private void showOneTextView(ViewHolder holder, int position) {
        TextView textview = (TextView) holder.findViewById(R.id.item_text);
        textview.setText(data.get(position).getName());
    }

    private void showTwoTextView(ViewHolder holder, int position) {
        TextView item_text_one = (TextView) holder.findViewById(R.id.item_text_one);
        TextView item_text_two = (TextView) holder.findViewById(R.id.item_text_two);
        item_text_one.setText(data.get(position).getName());
        item_text_two.setText(data.get(position).getType() + "");
    }

    private void showGridView(ViewHolder holder, int position) {
        TextView textview = (TextView) holder.findViewById(R.id.item_text);
        textview.setText(data.get(position).getName());
    }

    @Override
    public int getItemCount() {
        return data == null ? 0 : data.size();
    }

    //自定义的ViewHolder,持有每个Item的的所有界面元素
    public static class ViewHolder extends RecyclerView.ViewHolder {

        private Map<Integer, View> mCacheView;

        public ViewHolder(View itemView) {
            super(itemView);
            mCacheView = new HashMap<>();
        }

        public View findViewById(int resId) {
            View view;
            if (mCacheView.containsKey(resId)) {
                view = mCacheView.get(resId);
            } else {
                view = itemView.findViewById(resId);
                mCacheView.put(resId, view);
            }
            return view;
        }
    }
}

这里需要说一下,ViewHolder 我们这边统一做了封装,抽出findViewById方法,内部做了缓存处理,而简单的具体实例化交给各个具体item,方便使用。
2)我们知道普通的listview只有一列,而gridview是多列,recyclerview如何做到呢?其实是用到了layoutManager.setSpanSizeLookup方法.

public class MultiItemActivity extends AppCompatActivity {

    /**
     * view
     */
    private RecyclerView recyclerView;

    /**
     * 用来确定每一个item如何进行排列摆放,何时展示和隐藏
     */
    private GridLayoutManager layoutManager;

    /**
     * 适配器
     */
    private MultiItemAdapter mAdapter;

    private ArrayList<Person> data = new ArrayList<Person>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();
        initData();
    }

    /**
     * 初始化布局组件
     */
    private void initView() {
        recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        //创建默认的线性LayoutManager
        layoutManager = new GridLayoutManager(this, 2);
        recyclerView.setLayoutManager(layoutManager);
        //如果可以确定每个item的高度是固定的,设置这个选项可以提高性能
        recyclerView.setHasFixedSize(true);
    }

    /**
     * 初始化数据
     */
    private void initData() {
        for (int i = 0; i < 10; i++) {
            Person person = new Person();
            person.setName(i + "abc" + 1);
            if (i < 3) {
                person.setType(MultiItemAdapter.ONE_TEXT_VIEW_TYPE);
            } else if (i < 6) {
                person.setType(MultiItemAdapter.TWO_TEXT_VIEW_TYPE);
            } else {
                person.setType(MultiItemAdapter.GRID_VIEW_TYP);
            }
            data.add(person);
        }
        //创建并设置Adapter
        mAdapter = new MultiItemAdapter(this, data);
        recyclerView.setAdapter(mAdapter);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
            @Override
            public int getSpanSize(int position) {
                if (mAdapter.getItemViewType(position)
                        == MultiItemAdapter.GRID_VIEW_TYP) {
                    return 1;
                } else {
                    return 2;
                }
            }
        });
    }
}

在上面的基本设置中,我们的spanCount为2,setSpanSizeLookup可以让你根据position来设置spanCount,spanCount可以想象成布局里面的weight(比重),原先通过layoutManager = new GridLayoutManager(this, 2);设置成一个item占比为2,那么如果根据setSpanSizeLookup设置的spanCount为1的话,那么一行就是2列,这样才能满足一行的比重为2;如果spanCount为2的话,则说明一行一列。
通过上面的代码,我们就轻松的实现了多itemtype甚至listview跟gridview混合的情况。

4.完整代码下载地址如下所示:

demo下载链接


如有错误欢迎指出来,一起学习。
在这里插入图片描述

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值