我有以下 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 正在回收视图一样,并不关心加载栏的布局应该是不可见的。
我的适配器可能有什么问题?
答案 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)
}
// ...
}