ViewHolder点击是搞乱其他视图

时间:2018-06-13 15:38:20

标签: android scroll android-recyclerview kotlin android-viewholder

我有以下 RecyclerView.Adapter

class SpeciesAdapter(val activity: Activity, private val species: ArrayList<Specie>) : RecyclerView.Adapter<SpeciesAdapter.ViewHolder>() {

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

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val specie = species[position]
        holder.specie.text = specie.name
        holder.header.setOnClickListener {
            if (holder.information.visibility == View.GONE) showInformation(holder)
            else hideInformation(holder)
        }
    }

    private fun showInformation(holder: ViewHolder) {
        holder.information.visibility = View.VISIBLE
        holder.arrow.rotation = -90f
    }

    private fun hideInformation(holder: ViewHolder) {
        holder.information.visibility = View.GONE
        holder.arrow.rotation = 90f
    }

    override fun getItemCount() = species.size

    class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        val header: RelativeLayout = view.header_layout
        val arrow: ImageView = view.arrow_image
        val specie: TextView = view.specie_text
        val information: LinearLayout = view.information_layout
    }
}

正在制作这个:

https://media.giphy.com/media/9JcLhfgXOdt81WUxsE/giphy.mp4

您可以注意到,如果我单击某个项目,则会打开带有加载的布局。我的问题是,当我点击一个项目然后滚动时,其他一些项目也会打开,但我没有点击它们。就像 ViewHolder 正在回收视图一样,并不关心加载栏的布局应该是不可见的。

我的适配器可能有什么问题?

1 个答案:

答案 0 :(得分:1)

好的,您必须了解的是ViewHolder是一个可以在给定时间表示任何Specie对象的View。这个ViewHolder被RecyclerView重用,当有一些滚动时绑定到其他Specie对象,试图加载最少量的Views(这就是它被称为“Recycler”的原因)。

如果您只是更改Specie项目的持有者的属性,当重置持有者以显示另一个Specie对象时,如果您不“重置”它,该属性将保持不变。

简而言之,您必须在bind方法中设置所有ViewHolder属性,以确保持有者现在正确地表示将要显示的Specie对象。

那就是说,你要做的就是保持一个列表或地图,或者你想知道什么Specie对象在给定时间被“扩展”,并且当调用bind方法时,检查是否必须扩展或不扩展特定的Specie对象,并根据它显示持有者扩展信息。

使用问题解决方案进行编辑:

class SpeciesAdapter(val activity: Activity, private val species: ArrayList<Specie>) : RecyclerView.Adapter<SpeciesAdapter.ViewHolder>() {

    // added an ArrayList to store the opened species
    private val opened = arrayListOf<Specie>()

    // ...

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val specie = species[position]

        // added a condition to check if a specie was opened
        // and updates according to the result
        if (opened.contains(specie)) showInformation(holder, specie)
        else hideInformation(holder, specie)

        holder.specie.text = specie.name
        holder.header.setOnClickListener {
            if (holder.information.visibility == View.GONE) showInformation(holder, specie)
            else hideInformation(holder, specie)
        }
    }

    private fun showInformation(holder: ViewHolder, specie: Specie) {
        holder.information.visibility = View.VISIBLE
        holder.arrow.rotation = -90f

        // checking if is opened to avoid duplicates
        if (!opened.contains(specie)) opened.add(specie)
    }

    private fun hideInformation(holder: ViewHolder, specie: Specie) {
        holder.information.visibility = View.GONE
        holder.arrow.rotation = 90f

        // checking if exists to avoid crashes
        if (opened.contains(specie)) opened.remove(specie)
    }

    // ...
}