效果: 可以上下滑動看到分類, 左右滑動可以看到細項
Let’s Start
Step-by-Step Implementation
Step1 : Create Model classes for each of the RecyclerViews
CourseModel
package com.sqtek.nestedrecyclerview.model
data class CourseModel (val imageId: Int)
MainModel
package com.sqtek.nestedrecyclerview.model
data class MainModel (
val title: String,
val courseModels: List<CourseModel>
)
Step 2: Create FakeData class
SampleData
package com.sqtek.nestedrecyclerview.model
import com.sqtek.nestedrecyclerview.R
object SampleData {
private val courseModels = listOf(
CourseModel(R.drawable.course1),
CourseModel(R.drawable.course2),
CourseModel(R.drawable.course3),
CourseModel(R.drawable.course4),
CourseModel(R.drawable.course5),
CourseModel(R.drawable.course6),
CourseModel(R.drawable.course7),
CourseModel(R.drawable.course8),
)
val collections = listOf(
MainModel("All Course", courseModels),
MainModel("Want to take", courseModels.reversed()),
MainModel("Popular Course", courseModels.shuffled()),
MainModel("Top Rated", courseModels),
)
}
Step 3: Create RecyclerViews layout
Child layout (course_item.xml )
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<androidx.cardview.widget.CardView
android:layout_width="150dp"
android:layout_height="170dp"
android:layout_margin="5dp"
app:cardCornerRadius="5dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<ImageView
android:id="@+id/imageViewBook"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="8dp"
android:scaleType="centerCrop"/>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
Parent layout ( collection_item.xml )
<?xml version="1.0" encoding="utf-8"?>
<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="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/textViewCollectionTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
android:text="@string/app_name"
android:textSize="16sp"
android:textStyle="bold"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerViewBooks"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="8dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/course_item"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Step 4 : Working with Main Activity layout :
<?xml version="1.0" encoding="utf-8"?>
<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"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerViewCollections"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="8dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
tools:listitem="@layout/collection_item" />
</androidx.constraintlayout.widget.ConstraintLayout>
Step 5: Create an Adapter class for each of the RecyclerViews
Data需要通過Adapter來傳遞資料顯示在 RecyclerView 視圖中。 ChildItem 和 ParentItem 都需要Adapter。
Child Adapter (CourseAdapter.kt)
package com.sqtek.nestedrecyclerview
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.sqtek.nestedrecyclerview.databinding.CourseItemBinding
import com.sqtek.nestedrecyclerview.model.CourseModel
class CourseAdapter (private val courseModels: List<CourseModel>):
RecyclerView.Adapter<CourseAdapter.CourseViewHolder>() {
inner class CourseViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
val binding = CourseItemBinding.bind(itemView)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CourseViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.course_item, parent, false)
return CourseViewHolder(view)
}
override fun onBindViewHolder(holder: CourseViewHolder, position: Int) {
holder.binding.apply {
imageViewBook.setImageResource(courseModels[position].imageId)
}
}
override fun getItemCount(): Int {
return courseModels.size
}
}
Parent Adapter (MainAdapter.kt)
package com.sqtek.nestedrecyclerview
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.sqtek.nestedrecyclerview.databinding.CollectionItemBinding
import com.sqtek.nestedrecyclerview.model.MainModel
import com.sqtek.nestedrecyclerview.model.SampleData.collections
class MainAdapter(private val collection: List<MainModel>):
RecyclerView.Adapter<MainAdapter.CollectionViewHolder>() {
class CollectionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val binding = CollectionItemBinding.bind(itemView)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CollectionViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.collection_item, parent, false)
return CollectionViewHolder(view)
}
override fun onBindViewHolder(holder: CollectionViewHolder, position: Int) {
holder.binding.apply {
val collection= collections[position]
textViewCollectionTitle.text =collections[position].title
val courseAdapter = CourseAdapter(collection.courseModels)
recyclerViewBooks.adapter= courseAdapter
}
}
override fun getItemCount(): Int {
return collections.size
}
}
Step 6: Working with MainActivity.kt
package com.sqtek.nestedrecyclerview
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.sqtek.nestedrecyclerview.databinding.ActivityMainBinding
import com.sqtek.nestedrecyclerview.model.SampleData
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.apply {
recyclerViewCollections.adapter = MainAdapter(SampleData.collections)
}
}
}