宣告:原創作品,轉載請註明出處:www.jianshu.com/p/7d30ba789…
我在上一篇文章《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設定點選事件。
系列文章
《RecyclerView使用指南(一)—— 基本使用》
《RecyclerView使用指南(二)—— 多種ItemLayout》
《RecyclerView使用指南(三)—— 新增分割線和點選事件》
《RecyclerView使用指南(四)—— 使用ItemDecoration》
《RecyclerView使用指南(五)—— 實現吸頂效果》