RecyclerView使用指南(二)—— 多種ItemLayout
宣告:原創作品,轉載請註明出處: ofollow,noindex">https://www.jianshu.com/p/7d30ba789a46
我在上一篇文章 《RecyclerView使用指南(一)—— 基本使用》 中講解了RecyclerView的最基本用法。
這一篇,我來講解一下多種條目佈局應該如何顯示。(如果沒看過上一篇文章的小朋友,建議去看一下短小的上一篇文章。。。)
沒圖說個**:

- 核心思路:
- 針對不同的條目佈局,我們建立不同的ViewHolder。
- 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類,為了將它們放到同一個列表中,我們可以讓它們實現同一個介面,講到這裡,是不是有思路了呢?
好,我們來實現這個功能!
- 建立一個介面:
package com.liuym.myapplication; public interface IMultiType { /** * 返回條目型別 * * @return */ int getItemType(); }
- 建立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; } }
- 修改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); } } }
- 設定資料來源給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設定點選事件。