Custom Adapter RecyclerView Multiple View Type
Việc xây dựng RecylerView
có nhiều dòng item khác nhau cũng giống như RecyclerView
chỉ có 1 dòng item nhưng khác biệt ở custom adapter như sau:
- Tạo n ViewHolder ứng với n dòng item.
- Override lại phương thức
getItemViewType(int position)
để lấy về kiểu tương ứng với từng vị trí trong collection. - Phương thức
onCreateViewHolder()
phải dựa vào kiểu để tạo ViewHolder tương ứng. - Phương thức
onBindViewHolder()
phải dựa vào kiểu để gắn dữ liệu tương ứng vào ViewHolder.
Hướng dẫn tạo Custom Adapter
Tạo 3 file XML tương ứng với 3 dòng item như sau:
- row_text.xml: có 1
TextView
để hiển thị văn bản. - row_image.xml: hiển thị 1 hình ảnh
ImageView
. - row_user.xml: có 2
TextView
hiển thị tên và địa chỉ của user.
File row_text.xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_marginTop="3dp" android:layout_height="wrap_content"> <TextView android:background="#ecf0f1" android:padding="5dp" android:textColor="#2c3e50" android:id="@+id/tv_text" android:layout_width="match_parent" android:layout_height="wrap_content" /> </FrameLayout>
File row_image.xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="3dp"> <ImageView android:id="@+id/imv_image" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#95a5a6" /> </FrameLayout>
File row_user.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="3dp" android:background="#bdc3c7" android:orientation="vertical"> <TextView android:id="@+id/tv_name" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#34495e" android:textSize="18dp" /> <TextView android:id="@+id/tv_address" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#16a085" android:textSize="16dp" /> </LinearLayout>
Lớp User.java lưu thông tin User:
package com.eitguide.nguyennghia.recyclerviewmultipleviewtype; /** * Created by nguyennghia on 8/28/16. */ public class User { private String name; private String address; public User() { // TODO something } public User(String name, String address) { this.name = name; this.address = address; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
Tiếp theo, tiến hành tạo 1 CustomAdapter
.
Có 3 ViewHolder như sau:
TextViewHolder
public class TextViewHolder extends RecyclerView.ViewHolder { private TextView tvText; public TextViewHolder(View itemView) { super(itemView); tvText = (TextView) itemView.findViewById(R.id.tv_text); itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Toast.makeText(mContext, mObjects.get(getAdapterPosition()).toString(), Toast.LENGTH_SHORT).show(); } }); } }
ImageViewHolder
public class ImageViewHolder extends RecyclerView.ViewHolder { private ImageView imvImage; public ImageViewHolder(View itemView) { super(itemView); imvImage = (ImageView) itemView.findViewById(R.id.imv_image); itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Toast.makeText(mContext, mObjects.get(getAdapterPosition()).toString(), Toast.LENGTH_SHORT).show(); } }); } }
UserViewHolder
public class UserViewHolder extends RecyclerView.ViewHolder { private TextView tvName; private TextView tvAddess; public UserViewHolder(View itemView) { super(itemView); tvName = (TextView) itemView.findViewById(R.id.tv_name); tvAddess = (TextView) itemView.findViewById(R.id.tv_address); itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { User user = (User) mObjects.get(getAdapterPosition()); Toast.makeText(mContext, user.getName() + ", " + user.getAddress(), Toast.LENGTH_SHORT).show(); } }); } }
Override lại phương thức getItemViewType()
:
@Override public int getItemViewType(int position) { if (mObjects.get(position) instanceof String) return TEXT; else if (mObjects.get(position) instanceof Integer) return IMAGE; else if (mObjects.get(position) instanceof User) return USER; return -1; }
Override lại phương thức onCreateViewType()
:
@Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { LayoutInflater li = LayoutInflater.from(mContext); switch (viewType) { case TEXT: View itemView0 = li.inflate(R.layout.row_text, parent, false); return new TextViewHolder(itemView0); case IMAGE: View itemView1 = li.inflate(R.layout.row_image, parent, false); return new ImageViewHolder(itemView1); case USER: View itemView2 = li.inflate(R.layout.row_user, parent, false); return new UserViewHolder(itemView2); default: break; } return null; }
Override lại phương thức onBindViewHolder()
:
@Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { switch (getItemViewType(position)) { case TEXT: TextViewHolder textViewHolder = (TextViewHolder) holder; textViewHolder.tvText.setText(mObjects.get(position).toString()); break; case IMAGE: ImageViewHolder imageViewHolder = (ImageViewHolder) holder; imageViewHolder.imvImage.setImageResource((int) mObjects.get(position)); break; case USER: User user = (User) mObjects.get(position); UserViewHolder userViewHolder = (UserViewHolder) holder; userViewHolder.tvName.setText(user.getName()); userViewHolder.tvAddess.setText(user.getAddress()); break; } }
Source code toàn bộ CustomAdapter.java
package com.eitguide.nguyennghia.recyclerviewmultipleviewtype; import android.content.Context; import android.media.ImageWriter; 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 android.widget.Toast; import java.util.List; /** * Created by nguyennghia on 8/28/16. */ public class CustomAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private Context mContext; private List<Object> mObjects; public static final int TEXT = 0; public static final int IMAGE = 1; public static final int USER = 2; public CustomAdapter(Context context, List<Object> objects) { mContext = context; mObjects = objects; } @Override public int getItemViewType(int position) { if (mObjects.get(position) instanceof String) return TEXT; else if (mObjects.get(position) instanceof Integer) return IMAGE; else if (mObjects.get(position) instanceof User) return USER; return -1; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { LayoutInflater li = LayoutInflater.from(mContext); switch (viewType) { case TEXT: View itemView0 = li.inflate(R.layout.row_text, parent, false); return new TextViewHolder(itemView0); case IMAGE: View itemView1 = li.inflate(R.layout.row_image, parent, false); return new ImageViewHolder(itemView1); case USER: View itemView2 = li.inflate(R.layout.row_user, parent, false); return new UserViewHolder(itemView2); default: break; } return null; } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { switch (getItemViewType(position)) { case TEXT: TextViewHolder textViewHolder = (TextViewHolder) holder; textViewHolder.tvText.setText(mObjects.get(position).toString()); break; case IMAGE: ImageViewHolder imageViewHolder = (ImageViewHolder) holder; imageViewHolder.imvImage.setImageResource((int) mObjects.get(position)); break; case USER: User user = (User) mObjects.get(position); UserViewHolder userViewHolder = (UserViewHolder) holder; userViewHolder.tvName.setText(user.getName()); userViewHolder.tvAddess.setText(user.getAddress()); break; } } @Override public int getItemCount() { return mObjects.size(); } public class UserViewHolder extends RecyclerView.ViewHolder { private TextView tvName; private TextView tvAddess; public UserViewHolder(View itemView) { super(itemView); tvName = (TextView) itemView.findViewById(R.id.tv_name); tvAddess = (TextView) itemView.findViewById(R.id.tv_address); itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { User user = (User) mObjects.get(getAdapterPosition()); Toast.makeText(mContext, user.getName() + ", " + user.getAddress(), Toast.LENGTH_SHORT).show(); } }); } } public class TextViewHolder extends RecyclerView.ViewHolder { private TextView tvText; public TextViewHolder(View itemView) { super(itemView); tvText = (TextView) itemView.findViewById(R.id.tv_text); itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Toast.makeText(mContext, mObjects.get(getAdapterPosition()).toString(), Toast.LENGTH_SHORT).show(); } }); } } public class ImageViewHolder extends RecyclerView.ViewHolder { private ImageView imvImage; public ImageViewHolder(View itemView) { super(itemView); imvImage = (ImageView) itemView.findViewById(R.id.imv_image); itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Toast.makeText(mContext, mObjects.get(getAdapterPosition()).toString(), Toast.LENGTH_SHORT).show(); } }); } } }
Sau khi đã tạo xong CustomAdapter
thì thêm RecyclerView
vào main_activity.xml và cài đặt cho RecyclerView
trong MainActivity.java như sau:
File main_activity.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.eitguide.nguyennghia.recyclerviewmultipleviewtype.MainActivity"> <android.support.v7.widget.RecyclerView android:id="@+id/rv_multipe_view_type" android:layout_width="match_parent" android:layout_height="match_parent" /> </RelativeLayout>
Cài đặt trong MainActivity.java
package com.eitguide.nguyennghia.recyclerviewmultipleviewtype; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; private RecyclerView rvMultipleViewType; private List<Object> mData; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); rvMultipleViewType = (RecyclerView) findViewById(R.id.rv_multipe_view_type); mData = new ArrayList<>(); mData.add(new User("Nguyen Van Nghia", "Quan 11")); mData.add(R.drawable.avatar_1); mData.add("Text 0"); mData.add("Text 1"); mData.add(new User("Nguyen Hoang Minh", "Quan 3")); mData.add("Text 2"); mData.add(R.drawable.avatar_2); mData.add(R.drawable.avatar_3); mData.add(new User("Pham Nguyen Tam Phu", "Quan 10")); mData.add("Text 3"); mData.add("Text 4"); mData.add(new User("Tran Van Phuc", "Quan 1")); mData.add(R.drawable.avatar_4); mData.add(R.drawable.avatar_5); mData.add("Text 5"); mData.add(new User("Nguyen Ngoc Tien", "Quan 11")); mData.add(R.drawable.avatar_6); CustomAdapter adapter = new CustomAdapter(this, mData); rvMultipleViewType.setAdapter(adapter); rvMultipleViewType.setLayoutManager(new LinearLayoutManager(this)); } }
Mỗi phần tử trong danh sách đều có kiểu Object
từ đó có thể thêm bất cứ kiểu dữ liệu vào danh sách này (tất cả đối tượng trong Java đều kế thừa từ Object
).
Tải code sử dụng trong bài viết:
- Tải trực tiếp tại: RecyclerViewMultipleViewType-master.zip.
- Tải thông qua Github.