【问题标题】:Unable to Add setOnClickListener for RecyclerView items无法为 RecyclerView 项目添加 setOnClickListener
【发布时间】:2020-05-14 06:50:27
【问题描述】:

此应用程序使用 sharedPreferences 来填充 MainActivity.kt 中的回收器查看器。然后我想在每个回收器项目中有两个按钮,以便有一个事件侦听器将转到另一个活动。但是我一直无法这样做,试图操纵适配器和 MainActivity.kt。

MainActivity.kt:

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.activity_main.*
import java.io.File

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        populateRecycler()



        //Pressing GPS icon will go to adding a new location
        fabAddLocation.setOnClickListener { view -> addLocation(view) }
        }

    fun addLocation(x:View?){
        val locationIntent: Intent = Intent(this,AddLocation::class.java)
        startActivity(locationIntent)
    }

    fun createRecyclerContent(list :Array<String>): ArrayList<LocationItem> {

        //Get the shared preference file data
        var size = list.size
        val itemList = ArrayList<LocationItem>()
        for (i in 0 until size){
            val name = list[i].substring(0, list[i].length -4)
            lateinit var prefs:SharedPreferences

            prefs = getSharedPreferences(name,Context.MODE_PRIVATE)

            val getTitle = prefs.getString("Title","")
            val getDescription = prefs.getString("Description","")
            val getGps = prefs.getString("Longitude","")+","+prefs.getString("Latitude","")
            val listItem = LocationItem(R.drawable.ic_location_icon,getTitle.toString(),getDescription.toString(),getGps)

            itemList += listItem

        }
        return itemList

    }
    fun populateRecycler(){
        val sharedPrefsDir = File(applicationInfo.dataDir, "shared_prefs")
        if(sharedPrefsDir.exists() && sharedPrefsDir.isDirectory()){
            //verifying that the directory is found and that it has the names
            val locateList = sharedPrefsDir.list();
            //This should be sending the number of recycler items to my createRecyclerContent function, to populate the recycler

            val locationsList = createRecyclerContent(locateList)

            recycler_view.adapter=LocationsAdapter(locationsList)
            (recycler_view.adapter as LocationsAdapter).notifyDataSetChanged()
            recycler_view.layoutManager= LinearLayoutManager(this)
            recycler_view.setHasFixedSize(true)


        }
    }

适配器(LocationsAdapter):

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.ImageButton
import android.widget.TextView
import android.widget.Toast
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.saved_location_layout.view.*

class LocationsAdapter(private val locationList:List<LocationItem>):RecyclerView.Adapter<LocationsAdapter.LocationViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LocationViewHolder {
        //passes the layout to the recycler
        val itemView = LayoutInflater.from(parent.context).inflate(R.layout.saved_location_layout, parent, false)

        return LocationViewHolder(itemView)
    }

    override fun onBindViewHolder(holder: LocationViewHolder, position: Int) {
        val currentItem = locationList[position]

        holder.imageButton.setImageResource(currentItem.image)

        holder.textView1.text = currentItem.text1
        holder.textView2.text = currentItem.text2
        holder.textView3.text = currentItem.text3


    }
    //sets the count to the number of locations in the list
    override fun getItemCount() = locationList.size

    class LocationViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){

        val imageButton: ImageButton = itemView.btn_location
        val textView1: TextView = itemView.text_view_1
        val textView2: TextView = itemView.text_view_2
        val textView3: TextView = itemView.text_view_3
        val editButton:Button = itemView.btn_edit
    }
}

有两个按钮,btn_edit 和 btn_location,我需要每个按钮去另一个活动。非常感谢任何有关如何做到这一点的帮助。

【问题讨论】:

    标签: android kotlin android-recyclerview


    【解决方案1】:

    您可以为您的适配器创建一个简单的 ClickListener,例如像这样

    class LocationsAdapter(private val locationList:List<LocationItem>, private val listener: OnLocationButtonClickListener):RecyclerView.Adapter<LocationsAdapter.LocationViewHolder>() {
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LocationViewHolder {
            //passes the layout to the recycler
            val itemView = LayoutInflater.from(parent.context).inflate(R.layout.saved_location_layout, parent, false)
    
            return LocationViewHolder(itemView)
        }
    
        override fun onBindViewHolder(holder: LocationViewHolder, position: Int) {
            val currentItem = locationList[position]
            holder.bind(currentItem)
        }
        //sets the count to the number of locations in the list
        override fun getItemCount() = locationList.size
    
        inner class LocationViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
    
            val imageButton: ImageButton = itemView.btn_location
            val textView1: TextView = itemView.text_view_1
            val textView2: TextView = itemView.text_view_2
            val textView3: TextView = itemView.text_view_3
            val editButton:Button = itemView.btn_edit
    
            fun bind(item: LocationItem) {
    
               imageButton.setImageResource(item.image)
               imageButton.setOnClickListener {
                  listener.onImageClick(item)
               }
               textView1.text = item.text1
               textView2.text = item.text2
               textView3.text = item.text3
               editButton.setOnClickListener {
                  listener.onEditClick(item)
               }
            }
    
        }
    
    
        interface OnLocationButtonClickListener {
           fun onEditClick(item: LocationItem)
           fun onImageClick(item: LocationItem)
        }
    
    }
    

    在您的活动中,您只需实现侦听器,覆盖方法并将其传递给您的适配器

    class MainActivity : AppCompatActivity(), OnLocationButtonClickListener {
    
       ...
    
    
        fun populateRecycler(){
            val sharedPrefsDir = File(applicationInfo.dataDir, "shared_prefs")
            if(sharedPrefsDir.exists() && sharedPrefsDir.isDirectory()){
                //verifying that the directory is found and that it has the names
                val locateList = sharedPrefsDir.list();
                //This should be sending the number of recycler items to my createRecyclerContent function, to populate the recycler
    
                val locationsList = createRecyclerContent(locateList)
    
                recycler_view.adapter=LocationsAdapter(locationsList, this)
                (recycler_view.adapter as LocationsAdapter).notifyDataSetChanged()
                recycler_view.layoutManager= LinearLayoutManager(this)
                recycler_view.setHasFixedSize(true)
    
    
            }
    
            override fun onImageClick(item: LocationItem) {
               ...
            }
    
            override fun onEditClick(item: LocationItem) {
               ...
            }
    
        }
    

    希望这会有所帮助!

    【讨论】:

    • 非常感谢您的评论!当我尝试实现这一点时,我收到一个错误:`listener.onEditClick(item)` 我不确定是否应该在这里用“listener”替换其他东西?这个解决方案对我来说很有意义,只是不确定如何实现这个功能。再次感谢您的帮助
    • 对不起,我更新了我的答案,ViewHolder 类需要是inner class,然后你可以使用监听器
    • 谢谢!但是没有这条线:recycler_view.adapter=LocationsAdapter(locationsList, this) 使用“this”会引发错误。是否建议将侦听器更改为适配器的 MainActivity?如果我进行更改,那么整个 LocationsAdapter 都会抛出错误。再次感谢您的帮助
    • 您是否在创建适配器的 MainActivity 中实现了监听器?
    【解决方案2】:

    在 YourActivity 类(您想从回收站视图项按钮单击中打开)和伴随对象内部使用

        companion object {
    
           fun start(context: Context) {
                val intent = Intent(context, "YourActivity"::class.java)
                context.startActivity(intent)
            } 
        }
    

    在onBindViewHolder里面使用下面的代码调用

       override fun onBindViewHolder(holder: LocationViewHolder, position: Int) {
            val currentItem = locationList[position]
    
            holder.imageButton.setImageResource(currentItem.image)
    
            holder.textView1.text = currentItem.text1
            holder.textView2.text = currentItem.text2
            holder.textView3.text = currentItem.text3
           // you can use like this to visit your activity
            holder.editButton.setOnClickListener{
                         YourActivity.start(itemView.context)
                 }
        }
    

    【讨论】:

    • 谢谢!我已将此函数添加到我的活动类中,但是我对应该在我的 Viewholder 中调用它的位置感到困惑?你能帮忙澄清一下吗?
    • 我尝试添加到LocationViewHolder:class LocationViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){ val imageButton: ImageButton = itemView.btn_location val textView1: TextView = itemView.text_view_1 val textView2: TextView = itemView.text_view_2 val textView3: TextView = itemView.text_view_3 val editButton:Button = itemView.btn_edit val getEditor = editButton.setOnClickListener{ Edit.(itemView.context) } } 但是现在出现错误:表达式不能是选择器(出现在点之后)
    • 在 onBindViewHolder 函数上使用 holder.editButton.setOnClickListener{}
    • 你认为你可以编辑你的帖子来表达你的意思吗?我仍然在尝试实施时遇到问题。再次感谢您的帮助
    【解决方案3】:

    我在这里找到了解决问题的方法:Access application context in companion object in kotlin

    问题主要在于从传递给适配器的主要活动中获取正确的上下文。这是我现在正在运行的实现: MainAcitivity.kt:

    open class MainActivity : AppCompatActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            LocationsAdapter.setContext(this)
            populateRecycler()
    
    
            //Pressing GPS icon will go to adding a new location
            fabAddLocation.setOnClickListener { view -> addLocation(view) }
        }
    
        fun addLocation(x: View?) {
            val locationIntent: Intent = Intent(this, AddLocation::class.java)
            startActivity(locationIntent)
            overridePendingTransition(R.anim.slide_in, R.anim.fade_out)
    
        }
    
        fun createRecyclerContent(list: Array<String>): ArrayList<LocationItem> {
    
            //Get the shared preference file data
            var size = list.size
            val itemList = ArrayList<LocationItem>()
            for (i in 0 until size) {
                val name = list[i].substring(0, list[i].length - 4)
                lateinit var prefs: SharedPreferences
    
                prefs = getSharedPreferences(name, Context.MODE_PRIVATE)
    
                val getTitle = prefs.getString("Title", "")
                val getDescription = prefs.getString("Description", "")
                val getGps = prefs.getString("Longitude", "") + "," + prefs.getString("Latitude", "")
                val listItem = LocationItem(
                    R.drawable.ic_location_icon,
                    getTitle.toString(),
                    getDescription.toString(),
                    getGps
                )
    
                itemList += listItem
    
            }
            return itemList
    
        }
    
    
        fun populateRecycler() {
            val sharedPrefsDir = File(applicationInfo.dataDir, "shared_prefs")
            if (sharedPrefsDir.exists() && sharedPrefsDir.isDirectory()) {
                //verifying that the directory is found and that it has the names
                val locateList = sharedPrefsDir.list();
                //This should be sending the number of recycler items to my createRecyclerContent function, to populate the recycler
    
                val locationsList = createRecyclerContent(locateList)
    
                recycler_view.adapter = LocationsAdapter(locationsList)
                (recycler_view.adapter as LocationsAdapter).notifyDataSetChanged()
                recycler_view.layoutManager = LinearLayoutManager(this)
                recycler_view.setHasFixedSize(true)
    
    
            }
    
        }
    }
    *
    

    *LocationsAdapter 类文件:**

    class LocationsAdapter(private val locationList:List<LocationItem>):RecyclerView.Adapter<LocationsAdapter.LocationViewHolder>() {
    
        companion object {
            private lateinit var context: Context
    
            fun setContext(con:Context){
                context=con
            }
        }
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LocationViewHolder {
    
            //passes the layout to the recycler
    
            val itemView = LayoutInflater.from(parent.context).inflate(R.layout.saved_location_layout, parent, false)
    
            return LocationViewHolder(itemView)
        }
    
        override fun onBindViewHolder(holder: LocationViewHolder, position: Int) {
    
    
    
                fun EditALocation(context: Context) {
                    val intent = Intent(context, EditLocation::class.java).apply {
                        putExtra("TITLE_DATA",holder.textView1.text.toString())
                    }
                    context.startActivity(intent)
                }
    
            val currentItem = locationList[position]
    
    
            holder.imageButton.setImageResource(currentItem.image)
    
            holder.textView1.text = currentItem.text1
            holder.textView2.text = currentItem.text2
            holder.textView3.text = currentItem.text3
            holder.editButton.setOnClickListener {
               EditALocation(context)
            }
    
    
        }
    
        //sets the count to the number of locations in the list
        override fun getItemCount() = locationList.size
    
        class LocationViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
    
    
            val imageButton: ImageButton = itemView.btn_location
            val textView1: TextView = itemView.text_view_1
            val textView2: TextView = itemView.text_view_2
            val textView3: TextView = itemView.text_view_3
            val editButton:Button = itemView.btn_edit
    
            }
    
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多