Вы не описываете масштабирование, чтобы соответствовать; ты описываешь аспектное соответствие. (Я отредактировал ваш вопрос в этом отношении.) Подвид становится максимально большим, сохраняя соотношение сторон и полностью вписываясь в родительский элемент.
В любом случае, вы можете сделать это с помощью автоматического макета. Вы можете сделать это полностью в IB начиная с Xcode 5.1. Давайте начнем с некоторых взглядов:
Светло-зеленый вид имеет соотношение сторон 4: 1. Темно-зеленый вид имеет соотношение сторон 1: 4. Я собираюсь установить ограничения таким образом, чтобы синий вид заполнял верхнюю половину экрана, розовый вид заполнял нижнюю половину экрана, и каждый зеленый вид максимально расширялся, сохраняя при этом свое соотношение сторон и вписываясь в него. контейнер.
Сначала я создам ограничения для всех четырех сторон синего вида. Я прикреплю его к ближайшему соседу на каждом ребре с расстоянием 0. Я обязательно отключу поля:
Обратите внимание, что я пока не обновляю фрейм. Мне проще оставить пространство между представлениями при установке ограничений, и просто установить константы в 0 (или что-то еще) вручную.
Затем я прикрепляю левый, нижний и правый края розового изображения к ближайшему соседу. Мне не нужно устанавливать ограничение верхнего края, потому что его верхний край уже ограничен нижним краем синего вида.
Мне также нужно ограничение равных высот между розовым и синим видами. Это заставит их каждый заполнить половину экрана:
Если я скажу Xcode обновить все кадры сейчас, я получу это:
Так что ограничения, которые я установил до сих пор, верны. Я отменяю это и начинаю работу над светло-зеленым видом.
Аспектная подгонка светло-зеленого вида требует пяти ограничений:
- Требуемое приоритетное соотношение сторон на светло-зеленом виде. Вы можете создать это ограничение в XIB или раскадровке с помощью Xcode 5.1 или более поздней версии.
- Ограничение обязательного приоритета, ограничивающее ширину светло-зеленого вида меньше или равной ширине его контейнера.
- Ограничение с высоким приоритетом, устанавливающее ширину светло-зеленого вида равным ширине его контейнера.
- Ограничение обязательного приоритета, ограничивающее высоту светло-зеленого вида меньше или равной высоте его контейнера.
- Ограничение с высоким приоритетом, устанавливающее высоту светло-зеленого вида равным высоте его контейнера.
Давайте рассмотрим два ограничения ширины. Ограничение «меньше или равно» само по себе недостаточно для определения ширины светло-зеленого изображения; много ширины будут соответствовать ограничению. Поскольку существует неоднозначность, autolayout попытается выбрать решение, которое минимизирует ошибку в другом (высокоприоритетном, но не обязательном) ограничении. Минимизация ошибки означает, что ширина должна быть как можно ближе к ширине контейнера, при этом не нарушая обязательное ограничение меньше или равное.
То же самое происходит с ограничением по высоте. И поскольку также требуется ограничение соотношения сторон, оно может максимизировать размер подпредставления только по одной оси (если только у контейнера не будет такое же соотношение сторон, как у подпредставления).
Итак, сначала я создаю ограничение соотношения сторон:
Затем я создаю равные ограничения ширины и высоты с контейнером:
Мне нужно отредактировать эти ограничения, чтобы они были меньше или равны:
Далее мне нужно создать еще один набор равных ограничений ширины и высоты с контейнером:
И мне нужно сделать эти новые ограничения меньше требуемого приоритета:
Наконец, вы попросили центрировать подпредставление в его контейнере, поэтому я установлю эти ограничения:
Теперь, чтобы протестировать, я выберу контроллер представления и попрошу Xcode обновить все кадры. Вот что я получаю:
К сожалению! Подвид расширился, чтобы полностью заполнить свой контейнер. Если я выберу его, то смогу увидеть, что на самом деле он сохранил свое соотношение сторон, но вместо аспектного соответствия он выполняет аспектное заполнение .
Проблема в том, что при ограничении «меньше или равно» имеет значение, какое представление находится на каждом конце ограничения, и XCode установил ограничение, противоположное моему ожиданию. Я мог бы выбрать каждое из двух ограничений и поменять местами его первый и второй элементы. Вместо этого я просто выберу подпредставление и изменим ограничения, чтобы они были больше или равны:
Xcode обновляет макет:
Теперь я делаю все то же самое с темно-зеленым видом снизу. Мне нужно убедиться, что его соотношение сторон составляет 1: 4 (Xcode странным образом изменил его размер, поскольку у него не было ограничений). Я не буду показывать шаги снова, так как они одинаковы. Вот результат:
Теперь я могу запустить его в симуляторе iPhone 4S, размер экрана которого отличается от используемого IB, и проверить вращение:
И я могу проверить в симуляторе iPhone 6:
Я загрузил свою последнюю раскадровку в этот список для вашего удобства.
Роб, твой ответ потрясающий! Я также знаю, что этот вопрос конкретно о достижении этого с помощью автоматического макета. Однако, просто для справки, я хотел бы показать, как это можно сделать в коде. Вы настраиваете вид сверху и снизу (синий и розовый) так, как показал Роб. Затем вы создаете кастом
AspectFitView
:AspectFitView.h :
AspectFitView.m :
Затем вы изменяете класс синего и розового видов в раскадровке на
AspectFitView
s. Наконец вы установили два выхода на ваш ViewControllertopAspectFitView
иbottomAspectFitView
и установить ихchildView
с вviewDidLoad
:Так что это не сложно сделать в коде, и он по-прежнему очень адаптируется и работает с представлениями с различными размерами и различными пропорциями.
Обновление июль 2015 : найти демонстрационное приложение здесь: https://github.com/jfahrenkrug/SPWKAspectFitView
источник
Мне нужно решение из принятого ответа, но выполненное из кода. Самый элегантный способ, который я нашел, это использование фреймворка Masonry .
источник
Это для macOS.
У меня есть проблема, чтобы использовать способ Роба для достижения аспектного соответствия в приложении OS X. Но я сделал это другим способом - вместо ширины и высоты я использовал ведущий, трейлинг, верх и низ.
В основном, добавьте два начальных пробела, где один>> 0 @ 1000 требует приоритет, а другой = 0 @ 250 с низким приоритетом. Сделайте те же настройки для трейлинга, верхнего и нижнего пространства.
Конечно, вам нужно установить соотношение сторон и центр X и центр Y.
И тогда работа сделана!
источник
Я обнаружил, что мне нужно поведение аспектной заливки, чтобы UIImageView поддерживал свое собственное соотношение сторон и полностью заполнял контейнерное представление. Смущает, что мой UIImageView нарушал ОБА высокоприоритетные ограничения равной ширины и равной высоты (описанные в ответе Роба) и рендеринг с полным разрешением.
Решением было просто установить приоритет сопротивления сжатия содержимого UIImageView ниже, чем приоритет ограничений равной ширины и равной высоты:
источник
Это отличный ответ @ rob_mayoff на подход, основанный на коде, использующий
NSLayoutAnchor
объекты и перенесенный в Xamarin. Для меняNSLayoutAnchor
и связанные с ним классы сделали AutoLayout намного проще для программирования:источник
Возможно, это самый короткий ответ с Masonry , который также поддерживает заполнение и растягивание аспектов.
источник