RecyclerView的点击事件的两种实现方式

RecyclerView的点击事件

RecyclerView中没有提供类似与setOnItemClickListener()这样的注册监听方法,而需要我们自己给子项具体的View去注册点击事件。相比与ListView来说,RecyclerView的功能更加强大,不仅可以实现对点击子项的响应,而且对子项的每一个view都可以轻松的实现点击响应。

下面通过两种方法来实现:

(一)在适配器的onBindViewHolder方法中去添加响应事件

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
		...
        //点击事件(对子项的监听),若想监听子项中的view,将itemView改成对于的Id即可
        holder.itemView.setOnClickListener {
            val index = holder.layoutPosition
			...
        }
    	
    }

Demo:这个示例用RecyclerView来显示歌曲列表,点击列表子项后通过Toast弹出具体点击了哪一首歌曲。

1.activity_main.xml:直接引入一个recyclerView控件即可

<?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/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />

</androidx.constraintlayout.widget.ConstraintLayout>

2.item子项的布局:这里主要用于显示:图片,歌手以及歌曲名字。用了cardView来形成圆角效果

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="100dp"
    app:cardCornerRadius="10dp"
    app:cardElevation="1dp"
    app:cardUseCompatPadding="true">

    <ImageView
        android:id="@+id/songImage"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:layout_margin="2dp"
        />

    <LinearLayout
        android:layout_width="276dp"
        android:layout_height="75dp"
        android:layout_gravity="end"
        android:orientation="vertical">

        <TextView
            android:id="@+id/song"
            android:layout_width="266dp"
            android:layout_height="40dp"
            android:textColor="#0800ff"
            android:textSize="20sp" />

        <TextView
            android:id="@+id/singer"
            android:layout_width="264dp"
            android:layout_height="29dp" />
    </LinearLayout>
</androidx.cardview.widget.CardView>	

3.res/values下的arrays.xml中存放歌曲信息

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="songName">
        <item>晴天</item>
        <item>我的一个道姑朋友</item>
        <item>城南花已开</item>
    </string-array>

    <string-array name="singer">
        <item>周杰伦</item>
        <item>双笙</item>
        <item>三亩地</item>
    </string-array>

    <integer-array name="songImage">
        <item>@mipmap/sunny_day</item>
        <item>@mipmap/a_friend_of_mine</item>
        <item>@mipmap/city</item>
    </integer-array>
</resources>

4.歌曲类

data class Song(var singer:String, val song:String, val imageId:Int)

5.全局Context的设置:因为要Toast是需要Context环境的。而在适配器类中是没有Context环境的。因此可以写一个全局Context的获取类MyApplication。

class MyApplication : Application() {

    companion object{
        lateinit var context : Context
    }

    override fun onCreate() {
        super.onCreate()
        context = applicationContext
    }
}

同时需要在AndroidManfest.xml中添加:Android:name=".MyApplication"
在这里插入图片描述

6.适配器的实现(在OnBindViewHolder中实现了点击事件)

class SongAdapter(val songList:List<Song>):
        RecyclerView.Adapter<SongAdapter.ViewHolder>() {
    inner class ViewHolder(view: View):RecyclerView.ViewHolder(view){
        val songImage : ImageView = view.findViewById(R.id.songImage)
        val song : TextView = view.findViewById(R.id.song)
        val singer : TextView = view.findViewById(R.id.singer)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context)
            .inflate(R.layout.song_item,parent,false)
        return ViewHolder(view)
    }

    override fun getItemCount() = songList.size

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val value = songList[position]
        holder.songImage.setImageResource(value.imageId)
        holder.song.text = value.song
        holder.singer.text = value.singer

        //点击事件
        holder.itemView.setOnClickListener {
            val id = holder.layoutPosition
            val name = songList[id]
            Toast.makeText(MyApplication.context,"点击了歌曲${name}",Toast.LENGTH_SHORT).show()

        }
    }
}

7.MainActivity

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val layoutManager = LinearLayoutManager(this)
        recyclerView.layoutManager = layoutManager
        val adapter = SongAdapter(getSongs())
        recyclerView.adapter = adapter
    }


    //加载数据
    private fun getSongs():List<Song>{
        val songList = ArrayList<Song>()
        val songName = resources.getStringArray(R.array.songName)
        val singer = resources.getStringArray(R.array.singer)
        val songImage = resources.obtainTypedArray(R.array.songImage)

        for( i in 0..songName.size-1){
            val temp = Song(singer[i],
                songName[i],
                songImage.getResourceId(i,R.mipmap.sunny_day))
            songList.add(temp)
        }
        return songList
    }
}

在这里插入图片描述

(二)写回调方法

若想在点击后实现AlertDialog,但是AlertDialog是需要依附于Activity的。全局的Context是不能用的。这时候就可以写一个回调方法,在MainActivity中来实现事件的监听。

修改适配器类的代码(修改处写了注释)

package com.example.recyclerviewtest

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.recyclerview.widget.RecyclerView

class SongAdapter(val songList:List<Song>):
        RecyclerView.Adapter<SongAdapter.ViewHolder>() {

    //1.定义接口类型的成员数据
    private var myItemClickListener : OnItemClickListener ?= null

    //2.定义接口
    interface OnItemClickListener{
        fun onItemClick(position:Int)
    }
    //3.set方法
    fun setOnItemClickListener(onItemClickListener : OnItemClickListener?){
        myItemClickListener = onItemClickListener
    }


    inner class ViewHolder(view: View):RecyclerView.ViewHolder(view){
        val songImage : ImageView = view.findViewById(R.id.songImage)
        val song : TextView = view.findViewById(R.id.song)
        val singer : TextView = view.findViewById(R.id.singer)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context)
            .inflate(R.layout.song_item,parent,false)
        return ViewHolder(view)
    }

    override fun getItemCount() = songList.size

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val value = songList[position]
        holder.songImage.setImageResource(value.imageId)
        holder.song.text = value.song
        holder.singer.text = value.singer

        //4.传入position
        holder.itemView.setOnClickListener {
            myItemClickListener!!.onItemClick(position)
        }
    }
}

在MainActivity中

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val layoutManager = LinearLayoutManager(this)
        recyclerView.layoutManager = layoutManager
        val songList = getSongs()
        val adapter = SongAdapter(songList)
        recyclerView.adapter = adapter

        adapter.setOnItemClickListener(object:SongAdapter.OnItemClickListener{
            override fun onItemClick(position: Int) {
                AlertDialog.Builder(this@MainActivity).apply {
                    setTitle("test")
                    setMessage("点击了${songList[position]}")
                    setCancelable(false)
                    setPositiveButton("OK"){dialog, which ->  }
                    setNegativeButton("Cancel"){dialog, which ->  }
                    show()
                }
            }
        })
    }

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值