-1

[Android] RecyclerView Multiple View Type

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

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí