Привязка представления onBindViewHolder противоречива - PullRequest
2 голосов
/ 14 мая 2019

У меня есть ViewHolder, который должен отображаться по-разному в зависимости от того, находится ли он слева или справа от двух столбцов RecyclerView с GridLayoutManager.Обратите внимание на соединительные линии с каждой стороны вида:

<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, и поля обновляются соответственно.

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.Помните, что номера цитирования соответствуют позиции представления в пределах RecyclerView:

Actual behavior

Что происходит, чтобы изменить поведение?

Ответы [ 2 ]

6 голосов
/ 14 мая 2019

Я думаю, я знаю, что может помочь вам исправить это.Я предполагаю, что он повторно использует старое представление, как 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 будет использовать некоторыестарый взгляд, верно?Хорошо, так как обе строки VISIBLE в начале, вы предполагаете, что это их состояние по умолчанию.Но когда вы устанавливаете линии на GONE, вы никогда не возвращаете их обратно видимым, и, таким образом, если RecyclerView повторно использует это представление, это не добавит поля там, и просто пропустит соединительную линию.Вы всегда хотите иметь КАЖДУЮ строку кода в onBindViewHolder, чтобы иметь совпадающую строку, которая обращает ее.

3 голосов
/ 14 мая 2019

Хороший ответ Вуко, и в целом (всегда обновляйте каждый компонент вашего видоискателя) это то, что вы должны сделать абсолютно.

Однако я хотел бы добавить, что это выглядит так, как будто вы не следуетешаблон ViewHolder правильно: ваш метод onBindViewHolder() никогда не должен вызывать findViewById().Вместо этого ваш класс ViewHolder должен найти каждое представление один раз, а затем сохранить ссылки на них.

class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

    val connectorRight: ImageView = itemView.findViewById(R.id.citation_select_connector_right)
    val connectorLeft: ImageView = itemView.findViewById(R.id.citation_select_connector_left)
    // ...
}

И затем вы можете использовать эти поля непосредственно внутри onBindViewHolder():

if (position % 2 == 0) {
    holder.connectorRight.visibility = View.VISIBLE
    holder.connectorLeft.visibility = View.GONE
    // ...
} else {
    holder.connectorLeft.visibility = View.VISIBLE
    holder.connectorRight.visibility = View.GONE
    // ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...