Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/189.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android:启用RecyclerView.ViewHolder内的按钮_Android_Android Studio_Android Layout_Kotlin_Android Recyclerview - Fatal编程技术网

Android:启用RecyclerView.ViewHolder内的按钮

Android:启用RecyclerView.ViewHolder内的按钮,android,android-studio,android-layout,kotlin,android-recyclerview,Android,Android Studio,Android Layout,Kotlin,Android Recyclerview,我需要在布局(introscreen.xml)中启用一个按钮(id:readyButtonIntro)。为此,我在RecyclerView.ViewHolder中有另一个按钮 这是我需要访问的布局 introscreen.xml <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:androi

我需要在布局(introscreen.xml)中启用一个按钮(id:readyButtonIntro)。为此,我在RecyclerView.ViewHolder中有另一个按钮

这是我需要访问的布局

introscreen.xml

<?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"
    android:background="@color/colorWhite"
    tools:context=".IntroScreenVC">


    <LinearLayout
        android:id="@+id/indicatorContainer"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="40dp"
        android:gravity="center"
        android:orientation="horizontal"
        app:layout_constraintBottom_toBottomOf="parent" />

    <Button
        android:id="@+id/readyButtonIntro"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="16dp"
        android:layout_marginBottom="16dp"
        android:background="@color/colorWhite"
        android:textColor="@color/colorTerciary"
        android:alpha="0"
        android:enabled="false"
        android:text="Ready"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="15dp"
    >

    <Button
        android:id="@+id/addData"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:text="Agregar Datos"
        android:background="@drawable/button_rounded2"
        />

</LinearLayout>

我对IntroScreenVC很感兴趣,但总是有一个错误,即它为null,如果传递上下文或视图,则什么也不做


     fun readyButton(){

         readyButtonIntro.isEnabled = true
      }

你能帮我做这个吗?我会非常感激的。 非常感谢你! 问候


编辑:

我放置了适配器和ViewHolder以了解更多信息。 我忽略了这一点,因为我不想制造混乱。对不起

类构造函数


data class IntroSlide(val title: String, val description: String, val icon: Int, val firstButton: Boolean, val secondButton: Boolean, val thirdButton: Boolean)

vc.kt

class IntroScreenVC: AppCompatActivity() {

    private val introSliderAdapter = IntroScreenAdapter(
        listOf(
            IntroSlide(
                "title1",
            "description1",
                R.drawable.logo,
                false,
                false,
                false
            ),
            IntroSlide(
                "title2",
                "description2",
                R.drawable.doggrooming,
            true,
                false,
                false
            ),
            IntroSlide(
                "title3",
                "description3",
                R.drawable.introscreen3,
                false,
                true,
                false
            )
        )
    )

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

        introSliderViewPager.adapter = introSliderAdapter
    }
}


class IntroScreenAdapter(private val introSlides: List<IntroSlide>) : RecyclerView.Adapter<IntroSlideViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): IntroSlideViewHolder {

        val layoutInflater = LayoutInflater.from(parent?.context)
        val cellForRow = layoutInflater.inflate(R.layout.slide_item_container,parent,false)
        return IntroSlideViewHolder(cellForRow)
    }

    override fun getItemCount(): Int {
        return introSlides.size
    }

    override fun onBindViewHolder(holder: IntroSlideViewHolder, position: Int) {
        holder.bind(introSlides[position])

    }

}

class IntroSlideViewHolder(view: View) : RecyclerView.ViewHolder(view) {

    private val textTitle = view.findViewById<TextView>(R.id.textTitle)
    private val textDescription = view.findViewById<TextView>(R.id.textDescription)
    private val imageIcon = view.findViewById<ImageView>(R.id.imageSlideIcon)
    private val addData = view.findViewById<Button>(R.id.addData)
    private val addPet = view.findViewById<Button>(R.id.agregarMascota)

    val contexto = itemView.context;

    fun bind(introSlide: IntroSlide) {
        textTitle.text = introSlide.title
        textDescription.text = introSlide.description
        imageIcon.setImageResource(introSlide.icon)
        addData.isEnabled = introSlide.firstButton
        addPet.isEnabled = introSlide.thirdButton
        }
    }



    init {
        addData.setOnClickListener(View.OnClickListener {

           //ADD A ALERTDIALOG AND WHEN PRESS OK NEED TO ENABLE THAT BUTTON
            val mDialogView =  LayoutInflater.from(contexto).inflate(R.layout.alertdialog_add_data,null)
            val builder = AlertDialog.Builder(contexto)
            builder.setView(mDialogView)
            val dialog: AlertDialog = builder.create()
            dialog.show()
            dialog.getWindow()?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT));
            mDialogView.agregarDatosOK.setOnClickListener {
            //HERE I NEED TO ENABLE THE BUTTON 
            //readyButtonIntro(introscreen.xml)
            }
          }
}



class IntroSlideViewHolder(view: View) : RecyclerView.ViewHolder(view) {

    private val textTitle = view.findViewById<TextView>(R.id.textTitle)
    private val textDescription = view.findViewById<TextView>(R.id.textDescription)
    private val imageIcon = view.findViewById<ImageView>(R.id.imageSlideIcon)
    private val addData = view.findViewById<Button>(R.id.addData)
    private val addPet = view.findViewById<Button>(R.id.agregarMascota)

//INIT sharedPreferences
private val prefs: SharedPreferences = view.context.getSharedPreferences(getString(R.string.prefs_file), Context.MODE_PRIVATE)

    val contexto = itemView.context;

    fun bind(introSlide: IntroSlide) {
        textTitle.text = introSlide.title
        textDescription.text = introSlide.description
        imageIcon.setImageResource(introSlide.icon)
        addData.isEnabled = introSlide.firstButton
        addPet.isEnabled = introSlide.thirdButton
        }
    }



    init {
        addData.setOnClickListener(View.OnClickListener {
            val mDialogView = LayoutInflater.from(contexto).inflate(R.layout.alertdialog_add_data,null)
            val builder = AlertDialog.Builder(contexto)
            builder.setView(mDialogView)
            val dialog: AlertDialog = builder.create()
            dialog.show()
            dialog.getWindow()?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT));
            mDialogView.agregarDatosOK.setOnClickListener {


                    //HERE EDIT THE sharedPreferences
                    with (prefs.edit()) {
                        putBoolean("ready_button_enabled", true)
                        apply()
                    }

                    dialog.dismiss()

            }
          }
}


class IntroScreenVC: AppCompatActivity() {

    private val introSliderAdapter = IntroScreenAdapter(
        listOf(
            IntroSlide(
                "title1",
            "description1",
                R.drawable.logo,
                false,
                false,
                false
            ),
            IntroSlide(
                "title2",
                "description2",
                R.drawable.doggrooming,
            true,
                false,
                false
            ),
            IntroSlide(
                "title3",
                "description3",
                R.drawable.introscreen3,
                false,
                true,
                false
            )
        )
    )

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

        introSliderViewPager.adapter = introSliderAdapter
    }


    //HERE PUT THE RESUME TO EXPECT THE SHOW AND ENABLE THE BUTTON

    override fun onResume() {
        super.onResume()

        val prefs = getSharedPreferences(getString(R.string.prefs_file), Context.MODE_PRIVATE)
        val buttonEnabled = prefs.getBoolean("ready_button_enabled", false)
        readyButtonIntro.isEnabled = buttonEnabled
        if (buttonEnabled) {
            readyButtonIntro.alpha = 1f
        }else {
            readyButtonIntro.alpha = 0f

        }

    }
}



IntroScreenAdapter.kt

class IntroScreenVC: AppCompatActivity() {

    private val introSliderAdapter = IntroScreenAdapter(
        listOf(
            IntroSlide(
                "title1",
            "description1",
                R.drawable.logo,
                false,
                false,
                false
            ),
            IntroSlide(
                "title2",
                "description2",
                R.drawable.doggrooming,
            true,
                false,
                false
            ),
            IntroSlide(
                "title3",
                "description3",
                R.drawable.introscreen3,
                false,
                true,
                false
            )
        )
    )

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

        introSliderViewPager.adapter = introSliderAdapter
    }
}


class IntroScreenAdapter(private val introSlides: List<IntroSlide>) : RecyclerView.Adapter<IntroSlideViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): IntroSlideViewHolder {

        val layoutInflater = LayoutInflater.from(parent?.context)
        val cellForRow = layoutInflater.inflate(R.layout.slide_item_container,parent,false)
        return IntroSlideViewHolder(cellForRow)
    }

    override fun getItemCount(): Int {
        return introSlides.size
    }

    override fun onBindViewHolder(holder: IntroSlideViewHolder, position: Int) {
        holder.bind(introSlides[position])

    }

}

class IntroSlideViewHolder(view: View) : RecyclerView.ViewHolder(view) {

    private val textTitle = view.findViewById<TextView>(R.id.textTitle)
    private val textDescription = view.findViewById<TextView>(R.id.textDescription)
    private val imageIcon = view.findViewById<ImageView>(R.id.imageSlideIcon)
    private val addData = view.findViewById<Button>(R.id.addData)
    private val addPet = view.findViewById<Button>(R.id.agregarMascota)

    val contexto = itemView.context;

    fun bind(introSlide: IntroSlide) {
        textTitle.text = introSlide.title
        textDescription.text = introSlide.description
        imageIcon.setImageResource(introSlide.icon)
        addData.isEnabled = introSlide.firstButton
        addPet.isEnabled = introSlide.thirdButton
        }
    }



    init {
        addData.setOnClickListener(View.OnClickListener {

           //ADD A ALERTDIALOG AND WHEN PRESS OK NEED TO ENABLE THAT BUTTON
            val mDialogView =  LayoutInflater.from(contexto).inflate(R.layout.alertdialog_add_data,null)
            val builder = AlertDialog.Builder(contexto)
            builder.setView(mDialogView)
            val dialog: AlertDialog = builder.create()
            dialog.show()
            dialog.getWindow()?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT));
            mDialogView.agregarDatosOK.setOnClickListener {
            //HERE I NEED TO ENABLE THE BUTTON 
            //readyButtonIntro(introscreen.xml)
            }
          }
}



class IntroSlideViewHolder(view: View) : RecyclerView.ViewHolder(view) {

    private val textTitle = view.findViewById<TextView>(R.id.textTitle)
    private val textDescription = view.findViewById<TextView>(R.id.textDescription)
    private val imageIcon = view.findViewById<ImageView>(R.id.imageSlideIcon)
    private val addData = view.findViewById<Button>(R.id.addData)
    private val addPet = view.findViewById<Button>(R.id.agregarMascota)

//INIT sharedPreferences
private val prefs: SharedPreferences = view.context.getSharedPreferences(getString(R.string.prefs_file), Context.MODE_PRIVATE)

    val contexto = itemView.context;

    fun bind(introSlide: IntroSlide) {
        textTitle.text = introSlide.title
        textDescription.text = introSlide.description
        imageIcon.setImageResource(introSlide.icon)
        addData.isEnabled = introSlide.firstButton
        addPet.isEnabled = introSlide.thirdButton
        }
    }



    init {
        addData.setOnClickListener(View.OnClickListener {
            val mDialogView = LayoutInflater.from(contexto).inflate(R.layout.alertdialog_add_data,null)
            val builder = AlertDialog.Builder(contexto)
            builder.setView(mDialogView)
            val dialog: AlertDialog = builder.create()
            dialog.show()
            dialog.getWindow()?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT));
            mDialogView.agregarDatosOK.setOnClickListener {


                    //HERE EDIT THE sharedPreferences
                    with (prefs.edit()) {
                        putBoolean("ready_button_enabled", true)
                        apply()
                    }

                    dialog.dismiss()

            }
          }
}


class IntroScreenVC: AppCompatActivity() {

    private val introSliderAdapter = IntroScreenAdapter(
        listOf(
            IntroSlide(
                "title1",
            "description1",
                R.drawable.logo,
                false,
                false,
                false
            ),
            IntroSlide(
                "title2",
                "description2",
                R.drawable.doggrooming,
            true,
                false,
                false
            ),
            IntroSlide(
                "title3",
                "description3",
                R.drawable.introscreen3,
                false,
                true,
                false
            )
        )
    )

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

        introSliderViewPager.adapter = introSliderAdapter
    }


    //HERE PUT THE RESUME TO EXPECT THE SHOW AND ENABLE THE BUTTON

    override fun onResume() {
        super.onResume()

        val prefs = getSharedPreferences(getString(R.string.prefs_file), Context.MODE_PRIVATE)
        val buttonEnabled = prefs.getBoolean("ready_button_enabled", false)
        readyButtonIntro.isEnabled = buttonEnabled
        if (buttonEnabled) {
            readyButtonIntro.alpha = 1f
        }else {
            readyButtonIntro.alpha = 0f

        }

    }
}




解决方案:

进入活动(VC)

并将其插入适配器和RecyclerView


class IntroScreenAdapter(private val introSlides: List<IntroSlide>, val adapterOnClick: AdapterOnClick) : RecyclerView.Adapter<IntroScreenAdapter.IntroSliderViewHolder>() {


    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): IntroScreenAdapter.IntroSliderViewHolder {

        val layoutInflater = LayoutInflater.from(parent?.context)
        val cellForRow = layoutInflater.inflate(R.layout.slide_item_container,parent,false)
        return IntroSliderViewHolder(cellForRow)
    }

...

inner class IntroSliderViewHolder(view: View) : RecyclerView.ViewHolder(view) {

...

init {
            addData.setOnClickListener(View.OnClickListener {
                val mDialogView = LayoutInflater.from(contexto).inflate(R.layout.alertdialog_add_data,null)
                val builder = AlertDialog.Builder(contexto)
                builder.setView(mDialogView)
                val dialog: AlertDialog = builder.create()
                dialog.show()
                dialog.getWindow()?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT));
                mDialogView.agregarDatosOK.setOnClickListener {

                        //FINALLY HERE CHANGE THE BUTTON TO ENABLE :)
                 adapterOnClick.onClick()

}
}
}
}

类IntroScreenAdapter(私有val introSlides:List,val AdapterClick:AdapterClick):RecyclerView.Adapter(){
override fun onCreateViewHolder(父级:ViewGroup,viewType:Int):IntroScreenAdapter.IntroSliderViewHolder{
val layoutInflater=layoutInflater.from(父?.context)
val cellForRow=布局平坦。充气(右侧布局。幻灯片\项目\容器,父项,false)
返回IntroSliderViewHolder(cellForRow)
}
...
内部类IntroSliderViewHolder(视图:视图):RecyclerView.ViewHolder(视图){
...
初始化{
addData.setOnClickListener(View.OnClickListener{
val mDialogView=LayoutInflater.from(contexto).充气(R.layout.alertdialog\u add\u data,null)
val builder=AlertDialog.builder(contexto)
builder.setView(mDialogView)
val对话框:AlertDialog=builder.create()
dialog.show()
dialog.getWindow()?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT));
mDialogView.agregarDatosOK.setOnClickListener{
//最后在这里更改按钮以启用:)
adapterOnClick.onClick()
}
}
}
}

据我所知,您的问题属于a类,试图在B类中进行沟通(更改某些内容)。 根据您的具体需要,有几种解决此类问题的方法

从您提供的代码来看,布局和类之间的关系不够清晰,我无法给出更准确的答案。 首先,我知道您使用的是“回收者”视图。 一个recycler视图可以有许多项,我假设您希望能够从每个项启用该按钮

为了让IntroScreen类与viewholder通信,必须将引用传递给viewholder构造函数

为此,您可以实现一个简单的“回调模式”。 下面是定义接口(例如,用于启用按钮的函数)和实现回调的示例。 阅读一下Java中解释得很好的示例。在Kotlin中,您也可以采用同样的方法

以下是实施步骤的摘要:

  • 定义实现抽象方法enableButton的接口enableButton回调
  • 让InfoScreen类实现该接口(在其中启用按钮)
  • 将InfoScreen类传递给RecyclerView适配器,然后从适配器传递给ViewHolder
  • 在ViewHolder onClickListener中,调用接口方法enableButton
  • 更新2020/08/11 我尝试根据您更新的代码提供建议。 在介绍屏幕中,您设置了viewPager适配器,但仍然不清楚此属性来自何处以及它的确切显示位置。我猜您可能只是删除了参数定义。但是,我只是假设您的视图设置正确,这不是问题。对于将recycler view与viewPager一起使用,我发现了一些兴高采烈的消息

    我还不能清楚地看到您的用例。您是否一直在添加数据?那么您的屏幕中的按钮是否应该永久启用? 在这种情况下,可能是保存此类信息的好选择。即使它不需要保存,也需要保存。读取一个共享首选项文件是轻量级的,并且足够快,可以在主线程上完成。 我将在这里为您提供一个示例实现:

  • 获取共享首选项对象
  • 将sharedPref传递给适配器和viewHolder并写入:
  • 在屏幕中检查设置
  • 如果在单击“启用”按钮(将设置设置为true)后,需要返回到屏幕内活动:则可以在activities onResume方法中启用按钮 另一种解决办法是: 检查IntroScreen onClick方法中的设置。 那么你就不需要禁用这个按钮了。 您只需设置:

    // in your IntroScreen readyButtonIntro onClick method
    val buttonEnabled = sharedPref.getBoolean("ready_button_enabled", 
            false)
    if (!buttonEnabled) {
        // optional: write a Toast to notify the user why the button is doing nothing (yet)
        Toast.makeText(yourIntroScreenContext, "First agregar datos", Toast.LENGTH_SHORT).show()
        return // onClick returns, so nothing else will happen when clicked
    }
    ... // your code when the button **should** be enabled
    
    如果再次禁用按钮,只需将false保存到设置中即可

    由于我对您的用例不太了解,这对我来说似乎是一个简单而快速的解决方案。这样,您就不需要费心实现一个界面。无论如何,当您在viewHolder中单击按钮时,您的IntroScreen活动中没有立即的动作。您仍然希望用户返回IntroScreen并单击启用按钮。
    然后,在单击按钮时检查按钮是否已启用对我来说就足够了。

    在这种情况下,您可以使用该界面,将所有数据从适配器重定向到活动,在那里您必须访问主XML,并可以设置启用该按钮。

    感谢cewaphi的快速回复。是的,您理解正确。我有两个类IntroScreenVC:AppCompatActivity(){…}和另一个类IntroScreenAdapter(private val introSlides:List):RecyclerView.Adapter(){…}在ViewHolder中有setOnClickListener。我正试图按照你告诉我的做,但总是有相同的nul错误
    // in your IntroScreen readyButtonIntro onClick method
    val buttonEnabled = sharedPref.getBoolean("ready_button_enabled", 
            false)
    if (!buttonEnabled) {
        // optional: write a Toast to notify the user why the button is doing nothing (yet)
        Toast.makeText(yourIntroScreenContext, "First agregar datos", Toast.LENGTH_SHORT).show()
        return // onClick returns, so nothing else will happen when clicked
    }
    ... // your code when the button **should** be enabled