Nested RecyclerView

ν‘Έλ₯Έν•˜λŠ˜Β·2022λ…„ 5μ›” 31일
0
post-thumbnail

μ‹œν˜„ μ˜μƒ

πŸŽκ΅¬μ‘°λ„

🍎 Build grdale 에 DataBindnig μΆ”κ°€

 buildFeatures {
    dataBinding true
  }

🍎 데이터 클래슀 생성

childDTO.kt

data class ChildDTO(
    var title: String? = null,
    var description: String? = null,
    var imageURL: String? = null
)

ParentDTO.kt

data class ParentDTO(
    var title: String? = null,
    var description: String? = null,
    var children: List<ChildDTO>? = null,
)

🍎 데이터가 λ“€μ–΄κ°ˆ Repository Object 생성

object DataFactory {

    // to generate random numbers
    private val rand = Random(123123123L)

    // Sample titles
    private val titles = listOf("Vertigo",
        "The Innocents",
        "Lawrence of Arabia",
        "The Deer Hunter",
        "Amadeus",
        "Blade Runner",
        "Eyes Wide Shut"
    )

    // Sample descriptions
    private val descriptions = listOf(
        "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
        "Pellentesque sagittis odio ut tincidunt scelerisque.",
        "Phasellus a neque consequat leo bibendum tempus.",
        "Quisque at enim id odio blandit imperdiet nec consequat augue.",
        "Cras iaculis lorem a dignissim egestas.",
        "Duis quis leo pharetra, vestibulum elit rhoncus, tempus ante.",
        "Duis ut lorem aliquet, lobortis massa a, fringilla velit.",
        "Fusce non ipsum sed augue gravida ullamcorper."
    )

    // Returns a sample `ParentDTO` Object
    fun getParentList(): List<ParentDTO> {
        val list = ArrayList<ParentDTO>()
        for (i in 1..rand.nextInt(5, 10)) {
            list.add(ParentDTO(
                titles[rand.nextInt(titles.size)], descriptions[rand.nextInt(descriptions.size)], getChildList()
            ))
        }
        return list
    }

    // Returns a sample `List<ChildDTO>` Object to populate the parent object
    private fun getChildList(): List<ChildDTO> {
        val list = ArrayList<ChildDTO>()
        for (i in 1..rand.nextInt(5, 10)) {
            list.add(getRandomChild())
        }
        return list
    }

    // Returns a sample `ChildDTO` Object
    private fun getRandomChild(): ChildDTO {
        return ChildDTO(
            titles[rand.nextInt(titles.size)],
            descriptions[rand.nextInt(descriptions.size)],
            "@mipmap/img_sample"
        )
    }
}

🍎 μžμ‹ xml 생성 ( Child_item.xml)

<?xml version="1.0" encoding="utf-8"?>
<layout 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">

    <data>

        <import type="android.view.View" />

        <variable
            name="data"
            type="com.rishabh.nestedrecyclerview.dtos.ChildDTO" />
    </data>

    <androidx.cardview.widget.CardView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginHorizontal="4dp"
        android:layout_marginVertical="4dp"
        android:elevation="4dp">

        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="200dp"
            android:layout_height="wrap_content"
            android:background="@color/design_default_color_secondary"
            android:paddingHorizontal="8dp"
            android:paddingVertical="8dp">

            <ImageView
                android:id="@+id/iv_sub_image"
                android:layout_width="46dp"
                android:layout_height="46dp"
                android:contentDescription="@string/sublist_image"
                android:src="@mipmap/img_sample"
                android:textColor="@color/black"
                android:visibility="@{data.imageURL.isEmpty() ? View.GONE : View.VISIBLE}"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                tools:src="@tools:sample/avatars" />

            <TextView
                android:id="@+id/tv_sub_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="8dp"
                android:text="@{data.title}"
                android:textColor="@color/black"
                android:textStyle="bold"
                app:layout_constraintStart_toEndOf="@+id/iv_sub_image"
                app:layout_constraintTop_toTopOf="parent"
                tools:text="Sample Child Title" />

            <TextView
                android:id="@+id/tv_sub_description"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginStart="8dp"
                android:lines="2"
                android:text="@{data.description}"
                android:textColor="@color/black"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toEndOf="@+id/iv_sub_image"
                app:layout_constraintTop_toBottomOf="@+id/tv_sub_title"
                tools:text="Sample Child Description" />

        </androidx.constraintlayout.widget.ConstraintLayout>
    </androidx.cardview.widget.CardView>

</layout>

🍎 λΆ€λͺ¨ xml 생성 ( Parent_item.xml)

<?xml version="1.0" encoding="utf-8"?>
<layout 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">

    <data>

        <variable
            name="data"
            type="com.rishabh.nestedrecyclerview.dtos.ParentDTO" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:elevation="6dp"
        android:paddingHorizontal="8dp"
        android:paddingVertical="8dp">

        <TextView
            android:id="@+id/tv_title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textAlignment="center"
            android:textColor="#FF0000"
            android:fontFamily="monospace"
            android:textStyle="bold"
            android:text="@{data.title}"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            tools:text="Sample Parent Title" />

        <TextView
            android:id="@+id/tv_description"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textAlignment="center"
            android:text="@{data.description}"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/tv_title"
            tools:text="Sample Parent Description" />

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/rv_children"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/tv_description"
            tools:listitem="@layout/child_item" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

🍎 메인xml 생성 (activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<layout>

    <androidx.constraintlayout.widget.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="match_parent"
        android:paddingHorizontal="8dp"
        android:paddingVertical="8dp"
        tools:context=".MainActivity">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/rv_items"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            tools:listitem="@layout/parent_item" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

🍎 ChildAdapter.kt

class ChildAdapter(private val childData: List<ChildDTO>?) : RecyclerView.Adapter<ViewHolder>() {

    inner class ViewHolder(private val itemView: View, val binding: ChildItemBinding) : RecyclerView.ViewHolder(itemView)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val binding = DataBindingUtil.inflate(LayoutInflater.from(parent.context),
            R.layout.child_item, parent, false) as ChildItemBinding
        return ViewHolder(binding.root, binding)
    }

   override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    if ((childData?.size ?: 0) > position)
        holder.binding.data = childData?.get(position)

    holder.binding.executePendingBindings()
}

    override fun getItemCount() = childData?.size ?: 0
}

🍎ParentAdapter.kt

class ParentAdapter(private val data: List<ParentDTO>) : RecyclerView.Adapter<ViewHolder>() {

    inner class ViewHolder(private val itemView: View, val binding: ParentItemBinding) : RecyclerView.ViewHolder(itemView) {}

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val binding = DataBindingUtil.inflate(LayoutInflater.from(parent.context),
            R.layout.parent_item, parent, false) as ParentItemBinding
        return ViewHolder(binding.root, binding)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.binding.data = data[position]
        holder.binding.rvChildren.adapter = ChildAdapter(data[position].children)
        holder.binding.executePendingBindings()
    }

    override fun getItemCount() = data.size
}

🍎MainActivity.kt

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        val data = DataFactory.getParentList()
        binding.rvItems.adapter = ParentAdapter(data)

    }
}
profile
Developer-Android-CK

0개의 λŒ“κΈ€