如何使用RecyclerView(kotlin)

如何使用RecyclerView(kotlin)

情境

在 5.0 以後多了一個 RecyclerView,功能比 ListView 還強大,重點是用起來跟 ListView 大同小異,目前是全面取代 ListView 的利器。

完整程式碼

可以到 Github 上面觀看或下載程式碼

目前是轉成 androidX 版本,因此你需要升級你的 Gradle 以及導入的 Library。

implementation 'androidx.recyclerview:recyclerview:1.0.0'

接著在 xml 設定 RecyclerView。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/list_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</RelativeLayout>

在 MainActivity 初始化所有的元件,塞入假資料到 Adapter 裡面,一共有 99 筆資料。

class MainActivity : AppCompatActivity() {  
 override fun onCreate(savedInstanceState: Bundle?) {  
  super.onCreate(savedInstanceState)  
  setContentView(R.layout.activity_main)  
  val listData = ArrayList<String>()  
  for (i in 0..99) {  
     listData.add(i.toString())  
  }  
  val layoutManager = LinearLayoutManager(this)  
  layoutManager.orientation = LinearLayoutManager.VERTICAL  
  val dataList = findViewById<RecyclerView>(R.id.data_list)  
  dataList.layoutManager = layoutManager  
  dataList.adapter = DataAdapter(listData)  
 }  
}

這邊我們還沒有宣告 RecyclerView 的 Adpater,因此在同一個 class 底下設定好我們寫的 DataAdapter。

class DataAdapter(private val mData: List<String>) : RecyclerView.Adapter<ViewHolder>() {  
 override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {  
  val v = LayoutInflater.from(parent.context).inflate(R.layout.item, parent, false)  
  return ViewHolder(v)  
 }  

 override fun onBindViewHolder(holder: ViewHolder, position: Int) {  
  holder.dataView.text = mData[position]  
  holder.itemView.setOnClickListener { 
   Toast.makeText(it.context, "Item $position is clicked.", Toast.LENGTH_SHORT).show() 
  }  
  holder.itemView.setOnLongClickListener {  
   Toast.makeText(it.context, "Item $position is long clicked.", Toast.LENGTH_SHORT).show()  
   true
  }  
 }  

 override fun getItemCount(): Int {  
  return mData.size  
 }  
}

還有我們的 ViewHolder 也一起宣告起來。

class ViewHolder(v: View) : RecyclerView.ViewHolder(v) {  
 val dataView: TextView = v.findViewById(R.id.info_text)  
}

你會發現在 Kotlin 下的程式語法精簡了許多。
這時候看到 item.xml 還沒建立會出現紅字,因此我們補上 xml。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_margin="10dp"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <ImageView
        android:layout_centerVertical="true"
        android:id="@+id/info_img"
        android:layout_alignParentLeft="true"
        android:src="@drawable/flower"
        android:layout_width="50dp"
        android:layout_height="50dp" />
    <TextView
        android:layout_marginLeft="10dp"
        android:layout_centerVertical="true"
        android:layout_toRightOf="@id/info_img"
        android:layout_alignParentRight="true"
        android:id="@+id/info_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</RelativeLayout>

你會發現我們還是缺少了 flower.png 這個檔案,可以從這邊[下載]。(https://github.com/givemepassxd999/blog_files/blob/master/drawable/flower.png?raw=true)
這樣一執行就可以直接看到結果。

程式碼說明

一開始初始化 RecyclerView 一定要設定這幾行,裡面設置了 LayoutManager 是決定要橫向滑動還是直向滑動,另外還有必須設定 Adapter,這邊關乎到你在列表中,每一列的佈局是什麼。

val layoutManager = LinearLayoutManager(this)  
layoutManager.orientation = LinearLayoutManager.VERTICAL  
val dataList = findViewById<RecyclerView>(R.id.data_list)  
dataList.layoutManager = layoutManager  
dataList.adapter = DataAdapter(listData)

接著覆寫 RecyclerView.Adapter

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {}  
override fun onBindViewHolder(holder: ViewHolder, position: Int) {}  
override fun getItemCount(): Int {}

這邊透過覆寫三個方法來定義列表中的每一列的佈局,首先是 onCreateViewHolder 這個方法,跟 Adapter 表示哪個 xml 找到我們的 View, 接著在 onBindViewHolder 定義每一列內的元件要處理的事件或顯示,最後是 getItemCount 告訴 RecyclerView 一共有幾列,這樣就完成一個基礎的設置了,直接看效果。


說明一下我們在 onBindViewHolder 加入了兩個事件,一個是點擊事件另外一個是長按事件,都可以透過 holder.itemView 來完成。

holder.itemView.setOnClickListener { 
 Toast.makeText(it.context, "Item $position is clicked.", Toast.LENGTH_SHORT).show() 
}  
holder.itemView.setOnLongClickListener {  
 Toast.makeText(it.context, "Item $position is long clicked.", Toast.LENGTH_SHORT).show()  
 true  
}

對著某一列點擊就會觸發事件。


對著某一列長按住,就會觸發長按事件。

RecyclerView 系列可以參考。
如何使用RecyclerView
如何使用RecylerView+CardView
如何使用RecyclerView-控制LayoutManager
如何使用RecyclerView-左右滑刪除+移動位置