情境
在 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-左右滑刪除+移動位置