RecyclerView是Android中对ListView的升级,用来在有限的手机屏幕上展示大量的数据。除了用来展示数据,我们还可以为每个item,甚至每个item内的子控件设置监听器,以实现点击事件。
点击事件的实现方式有如下两种。
在onCreateViewHolder中注册点击事件
RecyclerView并非Android的原生空间,因此需要在build.gradle中添加依赖。
其次,在布局文件中添加RecyclerView。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="点击跳转"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_gravity="center_horizontal">
<!--这里应该把报名写全-->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recy"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />
</LinearLayout>
</LinearLayout>
接下来是准备适配器,我们的点击事件就在这里设置。
几个注意点:
函数名 | 功能 |
| 创建布局,创建 |
| 对RecyclerView的子项赋值,并设置其他属性 |
| 返回子项的个数 |
- 自定义的适配器继承自
RecyclerView.Adapter
。数据通过构造函数传进去。 - 内部类:
ViewHolder
。通过名字就可以看出来,他是包含Item子项布局的类。 - 需要重写的几个函数如下表
package com.example.recyclerview
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import android.widget.Toast
import androidx.recyclerview.widget.RecyclerView
import javax.sql.StatementEvent
class alphabetAdapter(val alphabetList:List<String>):RecyclerView.Adapter<alphabetAdapter.ViewHolder>() {
inner class ViewHolder(view:View):RecyclerView.ViewHolder(view){
val tv_letter:TextView = view.findViewById(R.id.tv_letter)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.alphabet, parent, false)
val viewHolder = ViewHolder(view)
//点击事件
viewHolder.tv_letter.setOnClickListener{
Toast.makeText(parent.context, "你点击了${viewHolder.tv_letter.text}", Toast.LENGTH_SHORT).show()
}
return viewHolder
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.tv_letter.text = alphabetList[position]
}
override fun getItemCount(): Int {
return alphabetList.size;
}
}
第一种方法的点击事件就写在函数onCreateViewHolder
,具体如下图。RecyclerView相比于LinearLayout的一个突出优点就是可以对子项中的每个子控件设置监听器。
最后附上调用此RecyclerView的Activity的代码,主要是初始化数据,设置布局管理器,设置适配器(Adapter
)。
package com.example.recyclerview
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.activity_main.*
import java.lang.StringBuilder
class MainActivity : AppCompatActivity() {
private val alphabetList = ArrayList<String>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
init()
btn.setOnClickListener{
startActivity(Intent(this, MainActivity2::class.java));
}
}
private fun init(){
alphabetList.add("Alpha")
alphabetList.add("Beta")
alphabetList.add("car")
alphabetList.add("duck")
alphabetList.add("eat")
alphabetList.add("fuck")
alphabetList.add("gg")
}
}
显示效果如下图:
这种方法设置监听器非常简单,容易理解,但是不易扩展。比如监听器需要用到Activity中的数据,传参不便,就需要在调用的地方设置监听器。这就需要用到下面的方法。
适配器中定义监听器接口
适配器
package com.example.myapplication
import android.view.LayoutInflater
import android.view.TextureView
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
class FruitAdapter(val fruitList: List<String>):RecyclerView.Adapter<FruitAdapter.ViewHolder>() {
inner class ViewHolder(view: View):RecyclerView.ViewHolder(view){
val tv:TextView = view.findViewById(R.id.tv)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.layout_item, parent, false)
return ViewHolder(view)
}
//点击事件
interface OnItemClickListerner{
fun onItemClick(position: Int)
}
private var mOnItemClickListerner:OnItemClickListerner? = null
public fun setOnItemClickListerner(onItemClickListerner:OnItemClickListerner?){
mOnItemClickListerner = onItemClickListerner
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.tv.text = fruitList[position]
holder.tv.setOnClickListener {
mOnItemClickListerner
}
}
override fun getItemCount(): Int = fruitList.size
}
Activity文件
package com.example.myapplication
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.LinearLayout
import android.widget.Toast
import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
private val frustList = ArrayList<String>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
init()
val adapter = FruitAdapter(frustList)
adapter.setOnItemClickListerner(object :FruitAdapter.OnItemClickListerner{
override fun onItemClick(position: Int) {
Toast.makeText(this@MainActivity, "你点击了${frustList.get(position)}", Toast.LENGTH_SHORT).show()
}
})
recy.adapter = adapter
recy.layoutManager = LinearLayoutManager(this)
}
fun init(){
frustList.add("苹果")
frustList.add("香蕉")
frustList.add("橘子")
frustList.add("菊花")
}
}
这里有五个关键点,下面一一列出。
- 定义接口
- 定义接口类型的数据成员。
- set方法
- 在
onBindViewHolder
传入position. - 在调用RecyclerView的地方(如Activity中)设置适配器,布局管理器等。