Я чувствую, что это довольно распространенная парадигма для показа / скрытия UIViews
, чаще всего UILabels
, в зависимости от бизнес-логики. Мой вопрос заключается в том, как лучше всего использовать AutoLayout для ответа на скрытые представления, как если бы их кадр был 0x0. Вот пример динамического списка 1-3 функций.
Прямо сейчас у меня есть 10px верхнее пространство от кнопки до последней метки, которая, очевидно, не будет скользить вверх, когда метка скрыта. На данный момент я создал выход для этого ограничения и изменил константу в зависимости от того, сколько меток я показываю. Это явно немного странно, так как я использую отрицательные значения констант, чтобы нажимать кнопку над скрытыми кадрами. Это также плохо, потому что он не ограничивается фактическими элементами макета, а просто скрытными статическими вычислениями, основанными на известных высотах / заполнении других элементов, и, очевидно, борется с тем, для чего был создан AutoLayout.
Очевидно, я мог бы просто создавать новые ограничения в зависимости от моих динамических меток, но это много микроуправления и многословия для попытки просто разрушить некоторые пробелы. Есть ли лучшие подходы? Изменить размер кадра 0,0 и позволить AutoLayout работать без ограничений? Удаление просмотров полностью?
Честно говоря, просто изменение константы из контекста скрытого представления требует одной строки кода с простым вычислением. Воссоздание новых ограничений с constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:
кажется таким тяжелым.
Редактировать февраль 2018 : ответ знакомства Бен с UIStackView
с
источник
Ответы:
UIStackView
Вероятно, это путь для iOS 9+. Он не только обрабатывает скрытый вид, но также удаляет дополнительные интервалы и поля при правильной настройке.источник
Лично я предпочитаю показывать / скрывать виды, чтобы создать IBOutlet с соответствующим ограничением ширины или высоты.
Затем я обновляю
constant
значение, чтобы0
скрыть, или любое другое значение, чтобы показать.Большим преимуществом этого метода является то, что относительные ограничения будут сохранены. Например, допустим, у вас есть вид A и вид B с горизонтальным зазором x . Когда view A width
constant
установлен в0.f
вид B переместится влево, чтобы заполнить это пространство.Нет необходимости добавлять или удалять ограничения, что является тяжелой операцией. Простое обновление ограничений
constant
сделает свое дело.источник
Решение использовать константу,
0
когда она скрыта, и другую константу, если вы показываете ее снова, является функциональным, но это неудовлетворительно, если ваш контент имеет гибкий размер. Вам нужно измерить ваш гибкий контент и установить постоянную обратно. Это кажется неправильным и имеет проблемы, если размер содержимого изменяется из-за событий сервера или пользовательского интерфейса.У меня есть лучшее решение.
Идея состоит в том, чтобы установить правило высоты 0 для высокого приоритета, когда мы скрываем элемент, чтобы он не занимал пространство для автоматической разметки.
Вот как вы это делаете:
1. установите ширину (или высоту) 0 в конструкторе интерфейсов с низким приоритетом.
Интерфейсный Разработчик не будет кричать о конфликтах, потому что приоритет низкий. Проверьте поведение высоты, временно установив приоритет 999 (1000 запрещается программно изменять, поэтому мы не будем его использовать). Разработчик интерфейса, вероятно, теперь будет кричать о конфликтующих ограничениях. Вы можете исправить это, установив приоритеты для связанных объектов на 900 или около того.
2. Добавьте выход, чтобы вы могли изменить приоритет ограничения ширины в коде:
3. Настройте приоритет, когда вы скрываете свой элемент:
источник
В этом случае я сопоставляю высоту метки Author с соответствующим IBOutlet:
и когда я устанавливаю высоту ограничения равной 0.0f, мы сохраняем «отступ», потому что высота кнопки воспроизведения позволяет это сделать.
источник
Здесь есть много решений, но мой обычный подход снова отличается :)
Установите два набора ограничений, аналогичных ответу Хорхе Аримани и TMin:
Все три отмеченных ограничения имеют одинаковое значение для Константы. Ограничения, отмеченные A1 и A2, имеют свой приоритет, установленный на 500, в то время как ограничение, отмеченное B, имеет свой приоритет, установленный на 250 (или
UILayoutProperty.defaultLow
в коде).Подключите ограничение B к IBOutlet. Затем, когда вы скрываете элемент, вам просто нужно установить высокий приоритет ограничения (750):
constraintB.priority = .defaultHigh
Но когда элемент виден, установите приоритет обратно на низкий (250):
constraintB.priority = .defaultLow
Преимущество этого подхода (по общему признанию, незначительное) перед простым изменением
isActive
ограничения B состоит в том, что у вас все еще есть рабочее ограничение, если временный элемент удаляется из представления другими средствами.источник
Подкласс просмотра и переопределения
func intrinsicContentSize() -> CGSize
. Просто вернитесь,CGSizeZero
если вид скрыт.источник
invalidateIntrinsicContentSize
. Вы можете сделать это переопределеноsetHidden
.Я только что узнал, что для того, чтобы UILabel не занимал пространство, вы должны скрыть его И установить его текст в пустую строку. (iOS 9)
Знание этого факта / ошибки может помочь некоторым людям упростить их макеты, возможно, даже те, которые были в оригинальном вопросе, поэтому я решил опубликовать его.
источник
Я удивлен, что не существует более элегантного подхода
UIKit
для этого желаемого поведения . Кажется, это очень распространенная вещь, чтобы хотеть быть в состоянии сделать.Поскольку подключение ограничений к
IBOutlets
их константам и установка их на состояние «0
неприятное» (и вызывалоNSLayoutConstraint
предупреждения, когда у вашего представления были подпредставления), я решил создать расширение, которое дает простой подход с отслеживанием состояния для скрытия / показаUIView
объекта с ограничениями Auto Layout.Он просто скрывает вид и удаляет внешние ограничения. Когда вы снова показываете представление, оно добавляет ограничения обратно. Единственное предостережение в том, что вам нужно будет указать гибкие ограничения отработки отказа для окружающих видов.
Редактировать Этот ответ предназначен для iOS 8.4 и ниже. В iOS 9 просто используйте
UIStackView
подход.источник
Лучше всего, когда все имеет правильные ограничения макета, добавить высоту или с ограничением, в зависимости от того, как вы хотите, чтобы окружающие виды перемещались и связывали ограничение в
IBOutlet
свойстве.Убедитесь, что ваши свойства
strong
в коде вы просто должны установить константу равной 0 и активировать ее, скрыть содержимое или деактивировать его, чтобы показать содержимое. Это лучше, чем связываться с константой и ее сохранением-восстановлением. Не забудьте позвонить
layoutIfNeeded
потом.Если содержимое, которое нужно скрыть, сгруппировано, лучше всего поместить все в представление и добавить ограничения для этого представления.
Как только у вас есть настройки, вы можете проверить их в IntefaceBuilder, установив ограничение на 0, а затем вернувшись к исходному значению. Не забудьте проверить приоритеты других ограничений, чтобы при скрытии не возникало никаких конфликтов. Другой способ проверить это установить 0 и установить приоритет 0, но вы не должны забывать восстановить его с наивысшим приоритетом.
источник
Я строю категорию, чтобы легко обновлять ограничения:
Ответ здесь: Скрыть autolayout UIView: Как получить существующий NSLayoutConstraint, чтобы обновить этот
источник
Мой предпочтительный метод очень похож на предложенный Хорхе Аримани.
Я предпочитаю создавать несколько ограничений. Сначала создайте свои ограничения, когда вторая метка видна. Создайте выход для ограничения между кнопкой и второй меткой (если вы используете objc, убедитесь, что он сильный). Это ограничение определяет высоту между кнопкой и второй меткой, когда она видна.
Затем создайте другое ограничение, которое определяет высоту между кнопкой и верхней меткой, когда вторая кнопка скрыта. Создайте выход для второго ограничения и убедитесь, что этот выход имеет сильный указатель. Затем снимите
installed
флажок в построителе интерфейса и убедитесь, что приоритет первого ограничения ниже, чем приоритет второго ограничения.Наконец, когда вы скрываете вторую метку, переключаете
.isActive
свойство этих ограничений и вызываетеsetNeedsDisplay()
И это все, никаких магических чисел, никакой математики, если у вас есть несколько ограничений на включение и выключение, вы даже можете использовать коллекции розеток, чтобы держать их организованными по состоянию. (AKA хранит все скрытые ограничения в одной коллекции OutletCollection и не скрытые ограничения в другой и просто перебирает каждую коллекцию, переключая их статус .isActive).
Я знаю, что Райан Романчук сказал, что он не хотел использовать множественные ограничения, но я чувствую, что это не micromanage-y, а проще, чем динамическое создание представлений и ограничений программно (чего, я думаю, он хотел бы избежать, если бы я читаю вопрос правильно).
Я создал простой пример, надеюсь, он будет полезен ...
источник
Я также предоставлю свое решение, чтобы предложить разнообразие.) Я думаю, что создание выхода для ширины / высоты каждого элемента плюс интервал просто смешно и взрывает код, возможные ошибки и количество осложнений.
Мой метод удаляет все представления (в моем случае экземпляры UIImageView), выбирает, какие из них необходимо добавить обратно, и в цикле добавляет обратно каждое и создает новые ограничения. Это на самом деле очень просто, пожалуйста, следуйте. Вот мой быстрый и грязный код для этого:
Я получаю чистый, последовательный макет и расстояние. Мой код использует Masonry, я настоятельно рекомендую его: https://github.com/SnapKit/Masonry
источник
Попробуйте BoxView , он делает динамический макет кратким и читабельным.
В вашем случае это:
источник