Kotlin RecyclerView onItemClick

Я пытаюсь реализовать щелчок по элементу с помощью RecyclerView около 2 дней. Я попытался сделать все, что было предложено stackoverflow по этому вопросу. У меня уже нет никаких идей, что делать дальше. Поэтому я хочу спросить вас.

Это мой код:

    class CustomAdapter(var data: List<DataSource>, val clickListener: OnWordItemClickListener):
RecyclerView.Adapter<CustomAdapter.ViewHolder>() {

    class ViewHolder(view: View) : RecyclerView.ViewHolder(view)
    {
        val tv_front: TextView = view.findViewById(R.id.tv_front) as TextView
        val tv_back: TextView = view.findViewById(R.id.tv_back) as TextView
        // Define the click listener
        fun initialize(dataSource: DataSource, action: OnWordItemClickListener)
        {
            tv_front.text = dataSource._front
            tv_back.text = dataSource._back

            itemView.setOnClickListener {
                action.onItemClick(dataSource, adapterPosition)
            }
        }
    }

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

        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        /*val currentItem = data[position]
        holder.tv_front.text = currentItem._front
        holder.tv_back.text = currentItem._back*/

        holder.initialize(data[position], clickListener)
    }

    override fun getItemCount(): Int = data.size
}

interface OnWordItemClickListener
{
    fun onItemClick(dataSource: DataSource, position: Int)
}

И код из MainActivity:

    class MainActivity : AppCompatActivity(), OnWordItemClickListener {

    val PERMISSION_REQUEST_CODE: Int = 123
    private lateinit var linearLayoutManager: LinearLayoutManager
    lateinit var rv_allWords: RecyclerView
    lateinit var adapter: CustomAdapter
    lateinit var databaseHandler: DatabaseHandler
    lateinit var dataSource: DataSource

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

        permissions()

        rv_allWords = findViewById(R.id.rv_allWords) as RecyclerView
        linearLayoutManager = LinearLayoutManager(this)
        rv_allWords.layoutManager = linearLayoutManager

        databaseHandler = DatabaseHandler(this)
        val exampleList = databaseHandler.read_from()
        adapter = CustomAdapter(exampleList, this)
        rv_allWords.adapter = adapter
        adapter.notifyDataSetChanged()
    }

    fun permissions()
    {
        //var permissionStatus = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) +
                ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
                == PackageManager.PERMISSION_GRANTED)
        {
            // permission granted
        } else {
            ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE), PERMISSION_REQUEST_CODE)
        }
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        when(requestCode)
        {
            PERMISSION_REQUEST_CODE ->
            {
                if ((grantResults.isNotEmpty()) && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED)
                {
                    // permissions is granted. Continue the action or workflow
                    Toast.makeText(this, "Permissions granted", Toast.LENGTH_SHORT).show()
                } else {
                    // Explain to the user that the feature is unavailable because
                    // the features requires a permission the the user has denied
                    val alertDialog: AlertDialog? = this?.let {
                        val builder = AlertDialog.Builder(it)
                        builder.apply {
                            setPositiveButton(R.string.OK, DialogInterface.OnClickListener { dialog, id ->
                                finish()
                                System.exit(0)
                            })
                            setMessage("The app needs to save some data to external storage.")
                        }
                        builder.show()
                    }
                }
                return
            }
            // Add other 'when' line to check for other
            // permissions this app might request
            else ->
            {
                // Ignore all other requests
            }
        }
    }
    fun generateTestList(size: Int): List<DataSource> {
        val list = ArrayList<DataSource>()

        for (i in 0 until size)
        {
            val item = DataSource(i, "Item $i", "$i")
            list += item
        }
        return list
    }

    override fun onCreateOptionsMenu(menu: Menu?): Boolean {
        menuInflater.inflate(R.menu.menu, menu)

        return super.onCreateOptionsMenu(menu)
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        var id = item.itemId

        if (id == R.id.menu_refresh)
        {

        }
        return super.onOptionsItemSelected(item)
    }

    override fun onResume() {
        super.onResume()
        databaseHandler.read_from()
    }

    override fun onItemClick(dataSource: DataSource, position: Int) {
        Toast.makeText(this, dataSource._back, Toast.LENGTH_SHORT).show()
        Log.i("onItemClick", dataSource._back)
    }
}

Когда я запускаю приложение на устройстве или эмуляторе, ничего не происходит. То есть, когда я пытаюсь щелкнуть любой элемент в RecyclerView, мое сообщение не отображается, и приложение работает без ошибок. Извините за мой английский. Что еще я могу сделать?

Вы пытались сделать интерфейс внутренним интерфейсом recyclerview?

tronku 23.12.2020 17:45

Вы видите рябь, когда вы нажимаете на элементы?

Tenfour04 23.12.2020 18:00

@ Tenfour04 да, я знаю. Но я не вижу Toast или Log

scrapjack 24.12.2020 16:21

@tronku да, я должен сделать то, что ты сказал. Но это не работает :(

scrapjack 24.12.2020 16:29
0
4
523
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
  1. Где определяется itemView? Я могу ошибаться, но вы должны заменить itemView на view внутри initialize() метода.

  2. Попробуйте реализовать View.OnClickListener с помощью класса ViewHolder.

     class ViewHolder(val view: View) : RecyclerView.ViewHolder(view), View.OnClickListener {
     //(...)
         fun initialize(dataSource: DataSource, action: OnWordItemClickListener)
             {
                 tv_front.text = dataSource._front
                 tv_back.text = dataSource._back
    
                 view.setOnClickListener{action.onItemClick(dataSource, adapterPosition)}            
    
     }
    

ОБНОВЛЯТЬ: Итак, изучив остальную часть кода, я обнаружил два LinearLayout внутри xml, используемых для макета ViewHolder. Я удалил «родительский», и он начал работать. Вот row_item.xml после изменений.

<?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 = "wrap_content"
        android:gravity = "center_horizontal"
        android:orientation = "horizontal"
        android:clickable = "true"
        android:focusable = "true"
        android:background = "?attr/selectableItemBackground">

        <TextView
            android:id = "@+id/tv_front"
            android:layout_width = "wrap_content"
            android:layout_height = "wrap_content"
            android:padding = "3dp"
            android:text = "Front"
            android:textSize = "32sp"
            android:gravity = "left"
            android:layout_weight = "1" />

        <TextView
            android:id = "@+id/tv_back"
            android:layout_width = "wrap_content"
            android:layout_height = "wrap_content"
            android:padding = "3dp"
            android:text = "Back"
            android:textSize = "32sp"
            android:gravity = "right"
            android:layout_weight = "1" />

    </LinearLayout>

Когда я пишу «view.setOnClickListener», я сказал мне, что «представление» — это неразрешенная ссылка.

scrapjack 24.12.2020 16:19

Я сделал небольшую правку в коде. Сделайте параметр класса view. Поэтому вместо view: View напишите val view: View в качестве параметра класса.

MiqeyM 25.12.2020 20:19

Теперь «это» выделено. Несоответствие типов. Требуется: View.OnClickListener?. Найдено: ViewHolder.

scrapjack 26.12.2020 09:07

Виноват! Я реализовал его как LongClickListener. Попробуйте с новым редактированием! view.setOnClickListener{action.onItemClick(dataSource, adapterPosition}

MiqeyM 26.12.2020 14:02

был бы признателен, если бы это сработало для вас, пометив это как хороший ответ

MiqeyM 30.12.2020 18:22

К сожалению, это тоже не работает. Ни тосты, ни сообщения журнала не отображались. Я все время пробовал разные решения, но почему-то ничего не работает :(. У вас есть решение, которое вы используете в своих проектах?

scrapjack 31.12.2020 05:17

Да, у меня есть! Можете ли вы связать меня с вашим проектом, чтобы я мог взглянуть или описать вашу проблему дальше :)

MiqeyM 31.12.2020 13:44
ссылка на Github. Буду премного благодарен. @MiqeyM
scrapjack 03.01.2021 16:29

Когда приложение запущено, необходимо добавить некоторые записи в базу данных через инспектор базы данных. Затем закройте приложение и снова запустите его. В противном случае список будет пуст.

scrapjack 03.01.2021 16:38

Итак, я думаю, что нашел проблему. Мои изменения должны работать для вас только после того, как вы удалите один дополнительный LinearLayout (тот, который является родителем). После того, как я удалил его и оставил «дочерний», он начал работать. Изменения кода в обновлении :)

MiqeyM 05.01.2021 17:35

Спасибо 1000 раз! Можете ли вы кратко объяснить мне, почему это произошло? Как LinearLayout предотвратил это? :)

scrapjack 07.01.2021 16:29

Ну объяснить - другое дело. Я хотел бы изучить эту проблему, но это займет некоторое время;) так что будьте готовы услышать от меня, как только я узнаю, почему. Не могли бы вы отметить мой ответ как принятый? спасибо и рад, что смог помочь

MiqeyM 07.01.2021 20:14

Другие вопросы по теме