ConstraintLayout GONE представление занимает пространство

У меня есть ViewHolder с заголовком сверху, и этот заголовок становится видимым в конкретном случае. В большинстве других случаев заголовок устанавливается как GONE, Проблема в том, что когда заголовок установлен как GONE, его высота все еще вычисляется, а другие виды spread по-другому (с большим количеством места между).

Вот макет макета: план

Blueprint объяснение:

  1. Заголовок ограничен top, left а также right,
  2. Два вида ниже находятся в packed chain, ограниченный заголовком на top, ImageView к right и родитель к left а также bottom,

А вот скриншот из инспектора макета с выделенным заголовком, который установлен как GONE:

Согласно документации, вид заголовка при установке на GONE должен быть сокращен до точки с ограничениями из других представлений, все еще примененных к нему, но заголовок не должен занимать пространство макета и влиять на высоту ConstraintLayout как установлено wrap_content,

На этом скриншоте инспектора не ясно, что произошло на самом деле. Заголовок не виден, вид снизу явно ограничен родительской вершиной, но заголовок все еще отображается в инспекторе как полная ширина с указанной высотой.

Я не уверен, если это ошибка, или я должен заставить ConstraintLayout переоценить себя.

ОБНОВЛЕНИЕ XML:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">


    <TextView
        android:id="@+id/list_item_step_conversion_tv_header"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="@color/gray_very_light"
        android:padding="@dimen/activity_vertical_margin"
        android:text="@string/favorites"
        android:textColor="@android:color/black"
        android:textSize="@dimen/default_text_size"
        android:textStyle="bold"
        android:visibility="gone"
        tools:visibility="visible"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

    <TextView
        android:id="@+id/list_item_step_conversion_tv_title"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginEnd="16dp"
        android:layout_marginLeft="16dp"
        android:layout_marginRight="16dp"
        android:layout_marginStart="16dp"
        android:layout_marginTop="8dp"
        android:ellipsize="end"
        android:maxLines="1"
        android:textColor="@color/gray_dark"
        android:textSize="@dimen/medium_text_size"
        app:layout_constraintBottom_toTopOf="@+id/list_item_step_conversion_tv_description"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/list_item_step_conversion_iv_favorite"
        app:layout_constraintTop_toBottomOf="@+id/list_item_step_conversion_tv_header"
        app:layout_constraintVertical_chainStyle="packed"
        tools:text="Bicycling - light (10-11.9 mph)"/>

    <TextView
        android:id="@+id/list_item_step_conversion_tv_description"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:layout_marginLeft="0dp"
        android:layout_marginRight="16dp"
        android:layout_marginTop="4dp"
        android:ellipsize="end"
        android:maxLines="1"
        android:textColor="@android:color/black"
        android:textStyle="bold"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintLeft_toLeftOf="@+id/list_item_step_conversion_tv_title"
        app:layout_constraintRight_toLeftOf="@+id/list_item_step_conversion_iv_favorite"
        app:layout_constraintTop_toBottomOf="@+id/list_item_step_conversion_tv_title"
        tools:text="182 steps/minute"/>

    <ImageView
        android:id="@+id/list_item_step_conversion_iv_favorite"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="0dp"
        android:layout_marginRight="24dp"
        android:layout_marginTop="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/list_item_step_conversion_tv_header"
        app:srcCompat="@drawable/ic_not_liked"/>    
</android.support.constraint.ConstraintLayout>

ОБНОВЛЕНИЕ 2

После дополнительных наблюдений эта проблема возникает только после звонка notifyDataSetChanged в RecyclerView.Adapter, Вот скриншот состояния макета до и после нажатия на favorite значок одного из предметов.

Объяснение скриншотов:

  • С левой стороны, ViewHolder с видимым header вид включен position: 2, Элементы выше отображаются правильно.
  • После нажмите на favorite значок (элемент со значением 242), ViewHolder на position: 1 это тот, с видимым header вид, в то время как ViewHolder на position: 2 иметь header вид установлен как GONE, Я ожидал ViewHolder высота уменьшается и имеет такую ​​же высоту, как ViewHolder на position: 0,

Имея в виду, что это ViewHolder имел header установлен в VISIBLE в предыдущем состоянии, это может быть что-то с утилизацией, не уверен.

2 ответа

Я решил эту проблему, позвонив view.requestLayout()* в конце моего адаптера #getViewпосле обычного звонка binding.executePendingBindings(),

* Я использую старую школу Adapter прямо сейчас, так что вы должны искать RecyclerView.Adapterэквивалентно, наверное #onBindViewHolder()

Кажется, что макет на самом деле правильный - не обращайте внимания на рамку пропавшего объекта в инспекторе, когда виджет помечается как пропавший, мы не выкладываем его снова, так как он будет просто пропущен (в Studio мы делаем, чтобы предоставить более простой способ увидеть, что происходит, но нет смысла делать это на реальном устройстве).

Какую версию ConstraintLayout вы используете? Я, кажется, получаю правильное поведение здесь:

введите описание изображения здесь

После маркировки первый элемент исчез:

введите описание изображения здесь

Что сработало для меня, так это установка начальной видимости объекта на "утерянный" и изменение его видимости с помощью кода.

Некоторым это нравится:

Мой xml:

<androidx.appcompat.widget.AppCompatTextView
    android:id="@+id/tvMyobject"
    style="@style/myStyle"
    tools:text="@string/dummy_text"
    android:textAlignment="center"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toBottomOf="@id/anyotherobject"
    android:visibility="gone"
/>

Моя деятельность:

if (isSomethingToShow) {
    tvMyobject.setVisibility(View.VISIBLE);
    tvMyobject.setText(R.string.my_string_to_show);
}
Другие вопросы по тегам