繁体   English   中英

更新 Recycler 查看项目按钮在适配器外部的可见性时出错

[英]Error Updating Recycler View Item Button Visibility outside Adapter

我的目标是在每个 RecyclerView 项目中都有一个按钮,该按钮将在单击时出现,以便我更改按钮的可见性。 第一次点击它工作正常,但再次点击或在任何其他项目中它会使应用程序崩溃。

这是我得到的错误

这是我的 Adapter.kt

class Adapter (private val orders:ArrayList<Order>, private val listener : OnItemClickListener) : RecyclerView.Adapter<Adapter.ViewHolder>(){


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

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val currentItem = orders[position]
        holder.nrPedido.text = currentItem.id.toString()
        holder.distancia.text = currentItem.distancia.toString()+"km"
        holder.estado.text = currentItem.estado


    }

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

    inner class ViewHolder(itemView : View) : RecyclerView.ViewHolder(itemView),
    View.OnClickListener{

        val nrPedido : TextView = itemView.findViewById(R.id.textViewIDPedido)
        val distancia : TextView = itemView.findViewById(R.id.textViewDistancia)
        val estado : TextView = itemView.findViewById(R.id.textViewEstado)
        val buttonEstado : Button = itemView.findViewById(R.id.buttonEstado)
        val buttonAceitarRecusar : Button = itemView.findViewById(R.id.buttonAceitarRecusar)
        val buttonDados : Button = itemView.findViewById(R.id.buttonDados)

        init {
             itemView.setOnClickListener(this)
        }

        override fun onClick(p0: View?) {
            val holder = ViewHolder(itemView)
            val order = orders[adapterPosition]
            val position = adapterPosition
            if(position != RecyclerView.NO_POSITION && order != null) {
                listener.onItemClick(order,position,holder)
            }
        }
    }

    interface OnItemClickListener{
        fun onItemClick(order: Order,position: Int,holder: ViewHolder)
    }
}

这是我的 mainActivity,其中调用了 onItemClick 方法

override fun onItemClick(order: Order,position:Int,holder: Adapter.ViewHolder) {
        visible = visible?.not()
        if(arrayListPedidos.contains(order)){
            val clickedItem = arrayListPedidos[position]
            if(visible==true){
                holder.buttonDados.visibility = View.VISIBLE

            }else{
                holder.buttonDados.visibility = View.INVISIBLE
            }
        }else if(arrayListMeusPedidos.contains(order)){
            val clickedItem = arrayListMeusPedidos[position]
            if(visible==true){
                holder.buttonDados.visibility = View.VISIBLE

            }else{
                holder.buttonDados.visibility = View.INVISIBLE
            }
        }

    }

我认为这可能与未通知该项目正在更新有关,但也可能是我发送持有人的方式。 当我在该项目上单击一次时,它会将可见性更改为可见。 如果我再次单击(使其不可见)或者如果我单击任何其他项目,它会使应用程序崩溃。

ViewHolder视为一个高度易变的视图,您不想保留在Adapter外部使用的任何关于它的引用——如果我正确理解您想要实现的目标,我看到您将ViewHolder传递回MainActivity通过做这样的事情来完成:

class Adapter(
    private val orders: ArrayList<Order>,
    // Note: Modern callbacks are declared like this, don't worry about passing the
    // OnItemClickListener
    private val listener: ((Order) -> Unit)
) : RecyclerView.Adapter<ViewHolder> { // Note: Try to use your own ViewHolders

    // In situations like this you can use a map or some other data structure to keep track of what
    // order button is supposed to be visible or not. You could also keep track of this in the Order
    // class itself.
    private val isVisibleMap = mutableMapOf<Int, Boolean>().apply {
        orders.forEachIndexed { index, _ -> put(index, false) }
    }

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

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val currentItem = orders[position]
        // You must set the visibility during the binding
        holder.buttonDados.visibility = if (isVisibleMap[position]) {
            View.VISIBLE
        } else {
            View.GONE
        }
        holder.nrPedido.text = currentItem.id.toString()
        holder.distancia.text = currentItem.distancia.toString()+"km"
        holder.estado.text = currentItem.estado
        holder.itemView.setOnClickListener {
            // Here we update the visibility
            isVisibleMap[position] = !isVisibleMap[position]
            listener.invoke(currentItem)
        }
    }

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

    inner class ViewHolder(itemView : View) : RecyclerView.ViewHolder(itemView) {
        val nrPedido : TextView = itemView.findViewById(R.id.textViewIDPedido)
        val distancia : TextView = itemView.findViewById(R.id.textViewDistancia)
        val estado : TextView = itemView.findViewById(R.id.textViewEstado)
        val buttonEstado : Button = itemView.findViewById(R.id.buttonEstado)
        val buttonAceitarRecusar : Button = itemView.findViewById(R.id.buttonAceitarRecusar)
        val buttonDados : Button = itemView.findViewById(R.id.buttonDados)
    }
}

请记住,像这样的事情,从适配器更改项目的可见性,应该在适配器本身内处理。 希望能帮助到你!

编辑:如果您想从适配器外部以编程方式更改按钮可见性,您可以随时执行以下操作:

class Adapter ... {

fun changeButtonVisibility(isVisible: Boolean, pos: Int) {
  isVisibleMap[pos] = isVisible
  notifyItemChanged(pos)
} 

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM