当前位置: 首页 > 知识库问答 >
问题:

使用Kotlin的接口回调方法将数据从适配器传递到活动

公羊安怡
2023-03-14
<?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="wrap_content"
    android:layout_height="wrap_content"
    android:paddingTop="6dp"
    android:paddingBottom="6dp"
    app:layout_constraintHorizontal_chainStyle="spread">

    <RatingBar
        android:id="@+id/ratingBar"
        style="@style/Widget.AppCompat.RatingBar.Small"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="2dp"
        android:layout_marginEnd="8dp"
        android:isIndicator="true"
        android:numStars="3"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/button" />

    <Button
        android:id="@+id/button"
        android:layout_width="90dp"
        android:layout_height="60dp"
        android:layout_marginStart="8dp"
        android:layout_marginEnd="8dp"
        android:backgroundTint="@color/game_button_color"
        android:textColor="@color/game_button_text_color"
        app:autoSizeTextType="uniform"
        app:layout_constraintDimensionRatio="1"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
    package com.maxcell.sumitup

import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.RatingBar
import androidx.core.content.ContextCompat.startActivity
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView


class LevelsAdaptor(private val callbackInterface:CallbackInterface) : ListAdapter<Levels, LevelsAdaptor.LevelsViewHolder>(LevelsComparator()) {

    interface CallbackInterface {
        fun passDataCallback(main:Int,sub: Int,star: Int)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LevelsViewHolder {
        return LevelsViewHolder.create(parent)
    }

    override fun onBindViewHolder(holder: LevelsViewHolder, position: Int) {
        val current = getItem(position)
        holder.bind(
            current.id,
            current.mainLevel,
            current.subLevel,
            current.stars,
            current.unlocked
        )

    }


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



        private val btn: Button = itemView.findViewById(R.id.button)
        private val rating: RatingBar = itemView.findViewById(R.id.ratingBar)
        private val myContext = itemView.context
        //private val myContext: Context = sumView.context
        fun bind(ID: Int, ML: Int, SL: Int, Stars: Int, Unlocked: Boolean) {

            btn.text = ID.toString()
            btn.setTag(R.id.mainLevel, ML)
            btn.setTag(R.id.subLevel, SL)
            btn.setTag(R.id.visualLevel, ID)
            btn.setTag(R.id.currentLevelStars, Stars)
            rating.rating = Stars.toFloat()
            if (Unlocked==true){btn.isEnabled=true; btn.isClickable=true}else{btn.isEnabled=false; btn.isClickable=false}

            itemView.setOnClickListener {
                //Set your codes about intent here
                CallbackInterface.passDataCallback(ML,SL,Stars)
            }

        }



        companion object {
            fun create(parent: ViewGroup): LevelsViewHolder {
                val view: View = LayoutInflater.from(parent.context)
                    .inflate(R.layout.rv_storymode_items, parent, false)
                return LevelsViewHolder(view)
            }
        }
    }

    class LevelsComparator : DiffUtil.ItemCallback<Levels>() {
        override fun areItemsTheSame(oldItem: Levels, newItem: Levels): Boolean {
            return oldItem.id == newItem.id
        }

        override fun areContentsTheSame(oldItem: Levels, newItem: Levels): Boolean {
            return oldItem == newItem
        }
    }
}

我也没有百分之百地遵循它。在我共享的链接中,接口函数名为passDataCallback(),然后在OnBindViewholder中使用passResultCallback()。如果我使用passResultCallback,它不会解析,所以我不知道我是否做错了什么,或者它是否真的像我在上面的适配器中写的那样

我还没有在我的活动中收集这些数据,因为希望适配器至少首先被正确地编写,如果人们认为我需要完全重新考虑方法,我会听取建议。

下面是保存RecycerView的活动。这是我认为我应该启动新活动的地方

package com.maxcell.sumitup

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Button
import android.widget.Toast
import androidx.activity.viewModels
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.isVisible
import androidx.fragment.app.FragmentTransaction
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.activity_story_levels.*

class StoryLevels : AppCompatActivity(), View.OnClickListener {

    private lateinit var storyView: RecyclerView
    val numbers = mutableListOf(1,2,3,4,5,6,7,8,9,10)
    lateinit var btn1: Button
    lateinit var btn2: Button
    lateinit var btn3: Button
    lateinit var btn4: Button
    lateinit var btn5: Button
    lateinit var btn6: Button
    lateinit var btn7: Button
    lateinit var btn8: Button
    lateinit var btn9: Button
    lateinit var btn10: Button

    lateinit var popupLayout: ConstraintLayout
    lateinit var popupBTNstart:Button
    lateinit var popupBTNexit:Button




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

        storyView = findViewById(R.id.rv_storymode)

        btn1 = findViewById(R.id.button2)
        btn2 = findViewById(R.id.button3)
        btn3 = findViewById(R.id.button4)
        btn4 = findViewById(R.id.button5)
        btn5 = findViewById(R.id.button6)
        btn6 = findViewById(R.id.button7)
        btn7 = findViewById(R.id.button8)
        btn8 = findViewById(R.id.button9)
        btn9 = findViewById(R.id.button10)
        btn10 = findViewById(R.id.button11)

        btn1.text = numbers[0].toString()
        btn2.text = numbers[1].toString()
        btn3.text = numbers[2].toString()
        btn4.text = numbers[3].toString()
        btn5.text = numbers[4].toString()
        btn6.text = numbers[5].toString()
        btn7.text = numbers[6].toString()
        btn8.text = numbers[7].toString()
        btn9.text = numbers[8].toString()
        btn10.text = numbers[9].toString()

        btn1.setOnClickListener(this)
        btn2.setOnClickListener(this)
        btn3.setOnClickListener(this)
        btn4.setOnClickListener(this)
        btn5.setOnClickListener(this)
        btn6.setOnClickListener(this)
        btn7.setOnClickListener(this)
        btn8.setOnClickListener(this)
        btn9.setOnClickListener(this)
        btn10.setOnClickListener(this)

        popupLayout = findViewById(R.id.layout_pregame_intro)
        popupLayout.isVisible = false
        popupBTNexit = findViewById(R.id.popup_btn_exit)

        val levelsViewModel: LevelsViewModel by viewModels {
            LevelsViewModelFactory((application as MyApplication).repository2)}

        val adapter = LevelsAdaptor()
        rv_storymode.adapter = adapter
        rv_storymode.layoutManager = GridLayoutManager(applicationContext, 4);

        levelsViewModel.level1.observe(this) { newValue ->
            // Update the cached copy of the words in the adapter.
            newValue.let { adapter.submitList(it) }
        }
    }

    fun testMessage(){
        Toast.makeText(applicationContext,"this is toast message", Toast.LENGTH_SHORT).show()
    }
    override fun onClick(v: View?) {

        val levelsViewModel: LevelsViewModel by viewModels {
            LevelsViewModelFactory((application as MyApplication).repository2)}

        val adapter = LevelsAdaptor()
        rv_storymode.adapter = adapter
        rv_storymode.layoutManager = GridLayoutManager(applicationContext, 4);

        if (v != null) {
            when (v.id){
                R.id.button2->{
                    levelsViewModel.level1.observe(this) { newValue ->
                        // Update the cached copy of the words in the adapter.
                        newValue.let { adapter.submitList(it) }}
                }
                R.id.button3->{
                    levelsViewModel.level2.observe(this) { newValue ->
                        // Update the cached copy of the words in the adapter.
                        newValue.let { adapter.submitList(it) }}}
                R.id.button4->{
                    levelsViewModel.level3.observe(this) { newValue ->
                        // Update the cached copy of the words in the adapter.
                        newValue.let { adapter.submitList(it) }}}
                R.id.button5->{
                    levelsViewModel.level4.observe(this) { newValue ->
                        // Update the cached copy of the words in the adapter.
                        newValue.let { adapter.submitList(it) }}}
                R.id.button6->{
                    levelsViewModel.level5.observe(this) { newValue ->
                        // Update the cached copy of the words in the adapter.
                        newValue.let { adapter.submitList(it) }}}
                R.id.button7->{
                    levelsViewModel.level6.observe(this) { newValue ->
                        // Update the cached copy of the words in the adapter.
                        newValue.let { adapter.submitList(it) }}}
                R.id.button8->{
                    levelsViewModel.level7.observe(this) { newValue ->
                        // Update the cached copy of the words in the adapter.
                        newValue.let { adapter.submitList(it) }}}
                R.id.button9->{
                    levelsViewModel.level8.observe(this) { newValue ->
                        // Update the cached copy of the words in the adapter.
                        newValue.let { adapter.submitList(it) }}}
                R.id.button10->{
                    levelsViewModel.level9.observe(this) { newValue ->
                        // Update the cached copy of the words in the adapter.
                        newValue.let { adapter.submitList(it) }}}
                R.id.button11->{
                    levelsViewModel.level10.observe(this) { newValue ->
                        // Update the cached copy of the words in the adapter.
                        newValue.let { adapter.submitList(it) }}}
            }
        }
    }
}

当我单击其中一个按钮时,我的活动应该知道该级别的主级别、子级别和当前恒星

然后,我将启动一个新活动,以便将信息传递到我的迷你名中

注意:你会注意到我设置了按钮标签。这是我遵循的一种方法,如果使用接口工作良好,如果人们同意这是最好的方法,这可以被删除

...............编辑...............

更新了适配器代码,以便在适配器级别而不是在OnBindViewholder中初始化接口。

itemView.setOnClickListener {
                //Set your codes about intent here
                CallbackInterface.passDataCallback(ML,SL,Stars)
            }

我尝试将接口移到LevelsViewHolder中--这并没有修复它。

共有1个答案

惠诚
2023-03-14

将适配器更改为此

class LevelsAdaptor(private val onClick:(id:Int)->Unit) : ListAdapter<Levels, LevelsAdaptor.LevelsViewHolder>(LevelsComparator()) {

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

    override fun onBindViewHolder(holder: LevelsViewHolder, position: Int) {
        val current = getItem(position)
        holder.bind(
            current.id,
            current.mainLevel,
            current.subLevel,
            current.stars,
            current.unlocked
        )
    }
    
    inner class LevelsViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        private val btn: Button = itemView.findViewById(R.id.button)
        private val rating: RatingBar = itemView.findViewById(R.id.ratingBar)
        private val myContext = itemView.context
        //private val myContext: Context = sumView.context
        fun bind(ID: Int, ML: Int, SL: Int, Stars: Int, Unlocked: Boolean) {
            btn.text = ID.toString()
            btn.setTag(R.id.mainLevel, ML)
            btn.setTag(R.id.subLevel, SL)
            btn.setTag(R.id.visualLevel, ID)
            btn.setTag(R.id.currentLevelStars, Stars)
            rating.rating = Stars.toFloat()
            if (Unlocked==true){btn.isEnabled=true; btn.isClickable=true}else{btn.isEnabled=false; btn.isClickable=false}
            itemView.setOnClickListener {
                //Set your codes about intent here
                onClick(ID)
            }
        }
    }

    class LevelsComparator : DiffUtil.ItemCallback<Levels>() {
        override fun areItemsTheSame(oldItem: Levels, newItem: Levels): Boolean {
            return oldItem.id == newItem.id
        }

        override fun areContentsTheSame(oldItem: Levels, newItem: Levels): Boolean {
            return oldItem == newItem
        }
    }
}

在活动中初始化适配器

val adapter = LevelsAdaptor(){id->
    //TODO do something with id passed from adapter, e.g. create new fragment
}

我还建议使用Jetpack导航,您可以使用detail视图作为输入级别

 类似资料: