在 android 中看到像是底下這種可以上下滑的列表類資料,可以用 recycler view 呈現,是一個使用非常非常頻繁的元件。
如果資料超出畫面的話
可以上下滑顯示所有資料
起初都會做的手忙腳亂,多寫幾次就不會了
先從 build.gradle(Module:app) 中加入依賴
dependencies {
implementation "androidx.recyclerview:recyclerview:1.1.0"
}
這裡採用的是 androidx 而版本是 1.1.0
在要用來顯示列表的主要畫面加上 recycler view 的 widget
這裡裝一個滿版的 recycler view
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
還要一個 layout 用來表示一個 item 的畫面。這裡就簡單寫個 text view 跟 button
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@color/colorPrimary"
android:layout_margin="20dp"
android:padding="10dp"
android:orientation="horizontal"
android:gravity="center_vertical">
<TextView
android:id="@+id/textId"
android:text="id"
android:textSize="20sp"
android:textColor="@android:color/white"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<Button
android:id="@+id/btnClick"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="click"
android:textAllCaps="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
現在我們有了畫面,再來呢,還需要一個 adapter 控制每個 item 的內容
建立一個 class 並使其繼承於 RecyclerView.Adapter<>()
除此之外,我還想要用 constructor 接收 context 跟 data。context 是用來
class RecyclerViewAdapter(
private val context: Context,
private val data: List<String>
): RecyclerView.Adapter<>() {
}
也可以傳入 view model 給 adapter 取得資料
如果在這階段直接對class的紅底線按 alt+Enter 實現父類別方法的話,會有 ??? 的產生
class RecyclerViewAdapter(
private val context: Context,
private val data: List<String>
): RecyclerView.Adapter<>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ??? {
TODO("Not yet implemented")
}
override fun onBindViewHolder(holder: ???, position: Int) {
TODO("Not yet implemented")
}
override fun getItemCount(): Int {
TODO("Not yet implemented")
}
}
是因為他不知道要放什麼東西,所以要建立一個內部類別叫做 view holder,並放進角括號中做泛型
class RecyclerViewAdapter(
private val context: Context,
private val data: List<String>
): RecyclerView.Adapter<RecyclerViewAdapter.MyViewHolder>() {
class MyViewHolder(itemView: View): RecyclerView.ViewHolder(itemView){
val textId: TextView= itemView.findViewById(R.id.textId)
val btnClick: Button= itemView.findViewById(R.id.btnClick)
}
}
item 中的各個元件是在這裡面宣告,可以在這時候先寫好。完成後再去實現,就不會有 ??? 了
實現完後多出的三個方法
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
TODO("Not yet implemented")
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
TODO("Not yet implemented")
}
override fun getItemCount(): Int {
TODO("Not yet implemented")
}
三個方法的功能分別為
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
return MyViewHolder(LayoutInflater.from(context).inflate(R.layout.item_recycler_view, parent, false))
}
中文翻譯就是創立 view holder,並且要將其傳回給 item 用。中間塞入 item 的 layout。
第二個是每一個 item 在建立的時候會跑的方法,也就是你的資料有多少筆,他就會跑幾次。
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.apply{
textId.text= data[position]
btnClick.setOnClickListener {
Toast.makeText(context, "按下第 ${position+ 1} 個", Toast.LENGTH_SHORT).show()
// position 從零開始的
}
}
}
這個方法負責每一個 item 要顯示的東西或監聽事件。剛剛寫的 MyViewHolder 會從上面那個方法傳進來,就可以更改其內容。
最後這個最簡單,就只要回傳總共要顯示多少筆資料而已
override fun getItemCount(): Int = data.size
因為我們有從建構元中拿到資料,回傳其 size 即可
完成後就可以回到 activity 做最後準備了
一個 recycler view 除了需要剛剛做的 adapter 以外,還要有 layout manager,其中當然不只有 LinearLayoutManager能夠做使用,還可以用其他的 manager 做出不同的變化。用 setter 設置 adapter 跟 layout manager
val recyclerView: RecyclerView = findViewById(R.id.recyclerView)
recyclerView.apply {
adapter= RecyclerViewAdapter(context, listOf("第一個", "第二個", "第三個", "第四個", "第五個"))
layoutManager= LinearLayoutManager(context)
}
完成了以後就來看看成果吧。
點選按鈕的時候,會跳出 Toast 顯示是第幾個