[Android] RecyclerView Multiple View Type
Bài đăng này đã không được cập nhật trong 4 năm
updated : 2019/06/17
Giới Thiệu
**RecyclerView là gì **
Android RecyclerView là phiên bản ListView tiên tiến hơn với hiệu suất được cải thiện và các lợi ích khác
Nó hỗ trợ chúng ta xây dựng UI linh hoạt và đơn giản hơn (LinearLayoutManager , GridLayoutManager)
Đã có rất nhiều bài viết hươngs dẫn các bạn về recycleview căn bản các bạn có thể tham khảo tại đây :
https://developer.android.com/guide/topics/ui/layout/recyclerview
Trong bài viết này mình sẽ không nói về các vấn đề cơ bản này nữa mà sẽ đi sâu và hướng đẫn các bạn về 1 cái rất hay ho của nó đó là :
Custom View Type
Let go
Việc chúng ta xây dựng RecylerView có nhiều row item khác nhau cũng giống như RecyclerView chỉ có 1 row item nhưng có một chút khác biệt ở ở Custom Adapter như sau:
-
Phải tạo 2 ViewHolder ứng với 2 row item.
-
Override lại phương thức getItemViewType(position: Int) để get type tương ứng với từng position
-
Trong fun onCreateViewHolder dựa vào view type để tạo ViewHolder tương ứng.
-
- Trong fub onBindViewHolder dựa và view type để bind data tương ứng vào ViewHolder.
Sau đây tôi sẽ đi vào phần viết CustomAdapter.
Trước tiên mình xây dựng hai layouti file xml tương ứng với hai row item như sau:
typw_one.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView android:layout_width="64dp"
android:layout_height="64dp"
android:src="@drawable/ic_contact_mail_black_24dp"
android:layout_marginTop="16dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="16dp"
android:id="@+id/imageView2"/>
<TextView
android:id="@+id/tvContact"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/colorAccent"
android:text="type1"
android:textSize="16sp"
app:layout_constraintStart_toEndOf="@+id/imageView2"
android:layout_marginStart="16dp"
app:layout_constraintTop_toTopOf="@+id/imageView2"
app:layout_constraintBottom_toBottomOf="@+id/imageView2"/>
<View android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/colorAccent"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="8dp"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="8dp"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@+id/imageView2"/>
</android.support.constraint.ConstraintLayout>
type_two.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView android:layout_width="64dp"
android:layout_height="64dp"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="16dp"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="16dp"
android:src="@drawable/ic_account_circle_black_24dp"
android:id="@+id/imageView"/>
<TextView
android:id="@+id/tvAccount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/colorPrimary"
android:text="type1"
android:textSize="16sp"
app:layout_constraintStart_toEndOf="@+id/imageView"
android:layout_marginStart="16dp"
app:layout_constraintTop_toTopOf="@+id/imageView"
app:layout_constraintBottom_toBottomOf="@+id/imageView"/>
<View android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/colorAccent"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="8dp"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="8dp"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@+id/imageView"/>
</android.support.constraint.ConstraintLayout>
RecyclerView trong Layout
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:showIn="@layout/activity_main"
tools:context=".MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent">
</android.support.v7.widget.RecyclerView>
</android.support.constraint.ConstraintLayout>
Sau đó chúng ta sẽ tạo 1 Adapter mình đặt tên MainAdapter.tk Trong adapter này mình tạo thêm 2 inner class TypeOneViewHodel và TypeTwoViewHodel kế thừa RecyclerView.ViewHolder để hiển thị data cho tương type view
package com.antx.androidcore
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import kotlinx.android.synthetic.main.type_one.view.*
import kotlinx.android.synthetic.main.type_two.view.*
class MainAdapter(
private val typeOneList: MutableList<String>,
private val typeTwoList: MutableList<String>
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun onCreateViewHolder(p0: ViewGroup, p1: Int): RecyclerView.ViewHolder {
val inflater = LayoutInflater.from(p0?.context)
return when (p1) {
ViewType.TYPE_ONE.type -> {
val view = inflater.inflate(R.layout.type_one, p0, false)
TypeOneViewHodel(view)
}
else -> {
val view = inflater.inflate(R.layout.type_two, p0, false)
TypeTwoViewHodel(view)
}
}
}
override fun getItemCount(): Int {
return typeOneList.count() + typeTwoList.count()
}
override fun onBindViewHolder(p0: RecyclerView.ViewHolder, p1: Int) {
p0.apply {
when (p0) {
is TypeOneViewHodel -> p0.bind(typeOneList[p1])
is TypeTwoViewHodel -> p0.bind(typeTwoList[p1 - typeOneList.count() ])
}
}
}
override fun getItemViewType(position: Int): Int {
return when (position) {
in 0 until typeOneList.count() -> ViewType.TYPE_ONE.type
else -> ViewType.TYPE_TWO.type
}
}
inner class TypeOneViewHodel(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(item: String) {
with(itemView) {
tvContact.text = item
}
}
}
inner class TypeTwoViewHodel(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(item: String) {
with(itemView) {
tvAccount.text = item
}
}
}
}
enum class ViewType(val type: Int) {
TYPE_ONE(0),
TYPE_TWO(1)
}
Code thiết lập RecyclerView - Thiết lập LayoutManager và Adapter
fun initView() {
addTypeList1()
addTypeList2()
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.adapter = MainAdapter(typeOneList, typeTwoList)
}
fun addTypeList1() {
typeOneList.add("type 1 1")
typeOneList.add("type 1 2")
typeOneList.add("type 1 3")
typeOneList.add("type 1 4")
typeOneList.add("type 1 5")
}
fun addTypeList2() {
typeTwoList.add("type 2 1")
typeTwoList.add("type 2 2")
typeTwoList.add("type 2 3")
typeTwoList.add("type 2 4")
typeTwoList.add("type 2 5")
}
Kết Qủa :
Kết
Trong bài viết mình đã giới thiệu về cách Custom Adapter RecyclerView Multiple View Type . Hi vọng sau bài viết có thể giúp các bạn các sử dụng view type để áp dụng vào project của mình ví dụ như sử nó để làm header và footer cho recycle view của mình
Thanks for reading
All rights reserved