Проблемы макета UIStackView при изменении класса размера в UITableViewCell

У меня возникают проблемы с компоновкой моего горизонтального UIStackView в пользовательском UITableViewCell при отображении/скрытии arrangedSubviews при изменении horizontalSizeClass.

Мое представление стека содержит несколько подпредставлений, каждое из которых, в зависимости от конфигурации ячейки и класса размера, либо hidden, либо отображается. UIStackView предназначен для управления расположением отображаемых видов, но при вращении возникают проблемы с расположением.

Проблемы:

  • Иногда соответствующие подпредставления либо не отображаются, либо не скрываются, когда должны быть.
  • Иногда подпредставления располагаются ненадлежащим образом, не заполняя ширину представления стека.

Попытки:

Я попытался сделать несколько вещей для решения макета:

  • Переопределение viewWillTransitionToSize:transitionCoordinator для перезагрузки таблицы и/или принудительного макета
  • Переопределение viewWillTransitionToTraitCollection:withTransitionCoordinator для перезагрузки таблицы и/или принудительного макета
  • Переопределение layoutSubviews для перенастройки представления стека arrangedSubviews
  • Звонок [self setNeedsLayout], [self layoutIfNeeded] после настройки ячейки
  • Принудительное расположение в других местах
  • Изменение приоритетов ограничения макета подпредставления на 999
  • Ограничение UILabels до 1 строки и установка preferredMaxLayoutWidth
  • Настройка contentCompressionResistance и contentHuggingPriority на видах
  • Использование статического значения для rowHeight вместо UITableViewAutomaticDimension
  • И т. д.

Кажется, ничего не решает проблемы.

Кроме того, даже когда ячейки прокручиваются за пределы экрана или отображаются на экране, подготавливаются к повторному использованию и перенастраиваются, проблемы либо сохраняются, либо исчезают, либо возникают новые проблемы, несмотря на то, что я правильно сбрасываю ячейку prepareForReuse.


Пример проекта

Я создал пример проекта, чтобы проиллюстрировать проблемы макета. На данный момент я не уверен, является ли UIStackView ошибкой или я неправильно ее использую.

Пример проекта: https://github.com/bradgmueller/StackViewTest

В примере проекта используется пользовательский UITableViewCell с представлениями, настроенными в файле xib. Объекты строк создаются с различными конфигурациями, чтобы проиллюстрировать динамические макеты, которые должна принять ячейка:

  • С отступом / без отступа
  • Показывает разделитель или нет
  • Отображение/скрытие кнопки «Нравится»
  • Отображение/скрытие кнопки «Поделиться»
  • Отображение/скрытие кнопки информации, где одна кнопка информации существует для UIUserInterfaceSizeClassCompact, а другая для UIUserInterfaceSizeClassRegular

Существует текстовая метка с текстом, указывающим, какое из представлений следует отображать, чтобы помочь проиллюстрировать, когда представления отображаются/скрываются ненадлежащим образом. Кроме того, позади UIStackView существует красный фоновый вид, чтобы показать, когда представление стека не может заполнить ширину.

Скриншоты:

Исходный макет — без проблем Исходный макет - без проблем

После поворота — проблемы, отмеченные красным крестиком Вращение — возникают проблемы


Буду признателен за любую информацию, заранее спасибо!!


person beebcon    schedule 01.04.2016    source источник


Ответы (1)


Обычно представления стека довольно хороши, но когда они усложняются и управляют большим количеством представлений, они кажутся менее надежными.

Я обнаружил, что лучший способ избежать проблем с макетом — сделать одну или две вещи:

  1. Используйте несколько представлений стека. Вместо того, чтобы объединять все мои представления в одно и то же представление стека, наличие нескольких представлений стека меньшего размера кажется более надежным, поскольку каждое из них управляет меньшим количеством представлений.
  2. Удаление/повторная вставка представлений, а не их скрытие. Хотя представления стека должны обрабатывать «скрытые» представления так, как если бы они были удалены из иерархии, я получил гораздо лучшие результаты компоновки, когда фактически удалил их из иерархии.

Ex:

Более надежные результаты компоновки:

if (hideSubview == YES) {
    [subview removeFromSuperview];
} else {
    [stackView insertArrangedSubview:subview atIndex:0];
}

Не так надежен:

subview.hidden = hideSubview;
person beebcon    schedule 25.10.2017