android - onBindViewHolder 绑定(bind) View 不一致

标签 android android-recyclerview

我有一个 ViewHolder,根据它是在带有 GridLayoutManager 的两列 RecyclerView 的左侧还是右侧,它的显示方式会有所不同。注意 View 两侧的连接线:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools"
              android:layout_width="wrap_content"
              android:layout_marginTop="12px"
              android:layout_marginBottom="12px"
              android:layout_gravity="center"
              android:gravity="center_vertical"
              android:layout_height="wrap_content"
              android:id="@+id/citation_select_holder">
    <ImageView
            android:src="@drawable/connector_line"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:id="@+id/citation_select_connector_right"/>


    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                    xmlns:tools="http://schemas.android.com/tools"
                    android:layout_width="348px"
                    android:layout_height="104px"
                    android:layout_weight="1"
                    android:background="@drawable/button_background_white"
                    android:id="@+id/citation_select_citation_holder">

        <LinearLayout android:layout_width="wrap_content"
                      android:layout_height="wrap_content"
                      android:orientation="vertical"
                      android:layout_centerVertical="true"
                      android:layout_alignParentLeft="true"
                      android:layout_marginLeft="28px"

        >
            <TextView
                    tools:text="123456"
                    android:textAppearance="@style/citation_select_item_number"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:id="@+id/citation_select_citation_number_text"/>

            <TextView
                    tools:text="Pay by: Nov 18th, 2019"
                    android:textAppearance="@style/citation_select_item_due_date"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:id="@+id/citation_select_due_date_text"/>
            <TextView
                    tools:text="a category label"
                    android:textAppearance="@style/citation_select_item_category"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:id="@+id/citation_select_category_text"/>

        </LinearLayout>

        <TextView
                tools:text="$10.00"
                android:textAppearance="@style/citation_select_item_cost"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:layout_centerVertical="true"
                android:id="@+id/citation_select_cost_text" android:layout_marginRight="28px"/>

    </RelativeLayout>

    <ImageView
            android:src="@drawable/connector_line"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:id="@+id/citation_select_connector_left"/>


</LinearLayout>

ViewHolder

onBindViewHolder 被调用时,远离 View 出现一侧的连接线将消失,边距也会相应更新。

if (position % 2 == 0) {

    holder.itemView.findViewById<ImageView>(R.id.citation_select_connector_left).visibility = View.GONE
    val marginLayoutParams1 = holder.citationHolder.layoutParams as GridLayoutManager.LayoutParams
    marginLayoutParams1.setMargins(0, 12, 12, 12)
    holder.itemView.findViewById<LinearLayout>(R.id.citation_select_holder).layoutParams =
        marginLayoutParams1

} else {

    holder.itemView.findViewById<ImageView>(R.id.citation_select_connector_right).visibility = View.GONE
    val marginLayoutParams2 = holder.citationHolder.layoutParams as GridLayoutManager.LayoutParams
    marginLayoutParams2.setMargins(12, 12, 0, 12)
    holder.itemView.findViewById<LinearLayout>(R.id.citation_select_holder).layoutParams =
        marginLayoutParams2
}

滚动仅通过屏幕上的按钮以六个为增量完成。前两个页面正常加载:

Desired Behavior

但这种模式在引用 #14 处开始崩溃。请记住,引用编号对应的是 View 在 RecyclerView 中的位置:

Actual behavior

改变行为的原因是什么?

最佳答案

我想我知道什么可以帮助您解决这个问题。我认为它正在重用旧 View ,因为 RecyclerView 应该并且在您的代码中没有任何地方有一行将 connector 行的可见性设置回可见。

您应该为您的GONE 可见性添加将另一个设置为可见的代码:

if (position % 2 == 0) {

holder.itemView.findViewById<ImageView>(R.id.citation_select_connector_right).visibility = View.VISIBLE
holder.itemView.findViewById<ImageView>(R.id.citation_select_connector_left).visibility = View.GONE
val marginLayoutParams1 = holder.citationHolder.layoutParams as GridLayoutManager.LayoutParams
marginLayoutParams1.setMargins(0, 12, 12, 12)
holder.itemView.findViewById<LinearLayout>(R.id.citation_select_holder).layoutParams =
    marginLayoutParams1

} else {

holder.itemView.findViewById<ImageView>(R.id.citation_select_connector_left).visibility = View.VISIBLE
holder.itemView.findViewById<ImageView>(R.id.citation_select_connector_right).visibility = View.GONE
val marginLayoutParams2 = holder.citationHolder.layoutParams as GridLayoutManager.LayoutParams
marginLayoutParams2.setMargins(12, 12, 0, 12)
holder.itemView.findViewById<LinearLayout>(R.id.citation_select_holder).layoutParams =
    marginLayoutParams2
}

补充说明

RecyclerView 会重用一些旧 View ,对吧?好吧,因为这两行在开始时都是 VISIBLE,所以您假设这是它们的默认状态。但是,当您将行设置为 GONE 时,您永远不会将它们恢复为可见状态,因此如果 RecyclerView 重用该 View ,它不会在那里添加边距,它只会缺少连接线。您总是希望 onBindViewHolder 中的每一行代码都有一个匹配行来恢复它。

关于android - onBindViewHolder 绑定(bind) View 不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56134607/

相关文章:

java - 在 Recyclerview 中取消 CountDownTimer

android - Android中的 Activity 和 Intent 有什么区别?

Android 首选项 Activity 未正确更新

android - 为什么服务不工作 "immediately"?

java - 四问-计算器应用-Android Java

android - 我如何在RecyclerView Adapter中获得第二个模型的位置

java - Android View InflateException 在尝试启动应用程序时出现

android - RecyclerView 中的 ListView

android - 如何在android中闪烁通知图标? [完毕]

android - 设置内部 RecyclerView wrap_content 的高度