Как я могу использовать Autolayout для установки ограничений на мой UIScrollview?


176

Я потратил два дня на то, чтобы опробовать различные решения для подходов Mixed и Pure Autolayout, чтобы достичь того, что было тривиальной настройкой scrollview до autolayout, и теперь это официально - я, должно быть, слишком глуп. Я настраиваю это в основном в раскадровке (ну, это просто так).

Итак, вот моя просьба о помощи.

Viewtree:

UIView
-UIView
-UIView
..-UIScrollview
...-UIButton
...-UIButton
...-UIButton

Кнопки должны прокручиваться горизонтально (слева направо и наоборот). Может кто-нибудь, пожалуйста, дайте мне знать, как установить ограничения для достижения этого с помощью чистого Autolayout ???

-

Я попробовал смешанный подход, вот так:

UIView
- UIView
- UIView
..-UIScrollview
...-UIView (contentview)
....-UIButton
....-UIButton
....-UIButton

... и установка фиксированной ширины и высоты ограничения для contentviewи translatesAutoresizingMaskIntoConstraintsнастройки как на TechNote Apple. Кнопки и вид прокрутки настраиваются с использованием ограничений. Это приводит к прокрутке прокрутки (yay), но, увы, она прокручивается слишком далеко! Насколько я могу судить, ширина прокрутки как-то удваивается по сравнению с тем, что я установил для contentview ??? !!! ???

Я также пробовал использовать метод чистого размещения, как с, так contentviewи без. Все мнения есть translatesAutoresizingMaskIntoConstraints=NO, кроме self.view. Кнопки имеют фиксированные ограничения ширины / высоты и прикреплены ко всем четырем краям прокрутки. Ничего не прокручивается.

Так что я совершенно сбит с толку, почему не могу заставить его работать правильно. Любая помощь очень ценится, и если вам нужна другая информация, пожалуйста, обращайтесь!

ОБНОВЛЕНИЕ Снимок экрана с решением - ограничения buttonZ:

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

РЕДАКТИРОВАТЬ @ Джейми Форрест Таким образом, решение оказывается неправильным конечным ограничением для последней кнопки. Вместо 6441 значение, которое я установил, было отрицательным, -6441. Сложность в том, что при установке значения в раскадровке на панели инструментов «Pin» есть два параметра:

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

Текущее значение холста является отрицательным (приводит к отсутствию прокрутки), а параметр ниже является положительным (активация прокрутки). Это значит, что я не глупый, но, по крайней мере, полуслепой, наверное. Хотя, на мой взгляд, не беспокоит ли то, что XCode не показывает ошибку при «неправильной» настройке?

ВНОВЬ ИЗМЕНЕНО Теперь это забавно ... изменение конечного значения с -6441 (без прокрутки) на 6441 с прокруткой. Но мой старый друг, «слишком большой размер содержимого» вернулся, что привело к тому, что размер содержимого в два раза больше, чем должен быть! Чтобы получить правильную прокрутку содержимого, нужно было установить конечное ограничение на ZERO! Это неочевидно при работе в Storyboard, но, глядя на код @Infinity James, оно так и должно быть.


Где вы рассчитываете / устанавливаете размер контента для просмотра прокрутки? Ссылаясь на вашу первую попытку использования contentView, и вы сказали, что он прокручивается слишком далеко.
Тим

2
Насколько я знаю, вы не можете установить contentSizeиз UIScrollViewиспользования только автоматической компоновки. И именно contentSizeэто определяет, сколько вы можете прокрутить. Таким образом, вам придется установить это где-то вручную в конце концов. В остальном вы можете использовать ограничения макета для настройки рамок вида относительно друг друга.
Гийом

@ Джефф, размер контента фиксированный, он никогда не меняется. Я устанавливаю размер содержимого в раскадровке, вводя правильную высоту и ширину для просмотра контентов вручную, и я закрепляю высоту и ширину с ограничениями в раскадровке.
user1459524

Распечатайте ваш contentSize во время выполнения, посмотрите, соответствует ли он введенным вами значениям. ContentSize определяет, сколько прокрутки происходит, поэтому проблема с вашей первой попыткой связана с contentSize.
Тим

@Guillaume, так что подход "pure autolayout" не настолько чист? Но КАК мне установить contentSize вручную? Как я упоминал выше, я устанавливаю высоту / ширину представления содержимого с фиксированными значениями (в раскадровке). Но он прокручивается слишком далеко (2 раза).
user1459524

Ответы:


68

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

Вместо объяснения того, что не так в вашей настройке, я создал базовый пример проекта с очень похожей иерархией представления и настройкой ограничений, которую вы описали. Горизонтальная прокрутка работает, как и ожидалось, в примере проекта, который использует подход «Pure AutoLayout», который Apple описывает в Техническом примечании .

У меня также было много проблем с настройкой Auto Layout UIScrollView. Ключом к тому, чтобы заставить его работать, является уверенность в том, что все элементы в представлении прокрутки, взятые вместе, имеют ограничения, которые в конечном итоге связаны со всеми сторонами представления прокрутки и способствуют тому, чтобы система AutoLayout могла определять contentSize для представление прокрутки, которое будет больше, чем его рамка. Похоже, вы пытались сделать это в своем коде, но, возможно, у вас были некоторые лишние ограничения, которые делали contentSize слишком маленьким.

Также следует отметить, что, как уже упоминалось, с AutoLayout и UIScrollview вы больше не устанавливаете contentSize явно. Система AutoLayout рассчитывает contentSize на основе ваших ограничений.

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


2
СПАСИБО за образец проекта! Это работает, и, просматривая его, я сначала не смог найти никакой разницы в моем проекте! Я скопировал представления в свой проект, подозревая некоторые другие настройки, кроме ограничений, но он продолжал работать. Это заставило меня заметить, что ограничение трейлинга для последней кнопки в моем проекте имеет минус - перед ним, в то время как у вашего есть положительное значение! Изменение - на позитив включил прокрутку! Когда я поднимаю панель инструментов Pin, есть два варианта: Использовать значение Current Canvas, которое является отрицательным, и Scroll View (использовать текущее значение), которое является положительным ...?!
user1459524

О да. Отрицательное значение фактически уменьшит contentSize вида прокрутки, чтобы соответствовать тому факту, что задний край должен заканчиваться до конца кнопки. Рад, что образец проекта помог!
Джейми Форрест

Это много сделал. Проверьте мой обновленный ответ. Конечное значение на самом деле должно быть 0 (ноль), как кажется.
user1459524

6
Это печально, что мы должны делиться скриншотами вместо кода. Это потому, что Apple поощряет разработчиков использовать конструктор вместо предоставления лучшего API.
владимир славян

4
Совершенно не интуитивно понятно. Разработчики должны тратить часы и часы, чтобы понять, что происходит в голове создателей XCode.
Джош

49

LOL добро пожаловать в клуб глупости. Я один из основателей. : D

Для вертикальной прокрутки : единственный способ заставить его работать (iOS 8, Xcode 6 и чистая автопрокладка) - добавить следующие ограничения в мой вид прокрутки (все они связаны с суперпредставлением):

  • Равные ширины
  • Равные высоты
  • Центр Y Выравнивание
  • Выравнивание по центру X

Моя структура:

  UIView
   - ScrollView
    - Subview
    - Subview
    - Subview
    - Subview
    - ...

Это конечный результат:

демонстрация

Это настройка:

Настроить Полноэкранный

А вот и проект .

Надеюсь, это спасет кого-то от ПОПЫТОК В 5 утра. : D


Большое спасибо за помощь! Как вы получили подпредставление типа "subview" ?? Я смотрю на ваш проект в Xcode 6.2, и он называет эти маленькие прямоугольники «Subview» с единственным ограничением, что он имеет высоту 63px.
Андрей К

1
Приветствую! Это «Subview» на самом деле UIVIew. Это просто имя ... Вы можете напечатать что-нибудь там. Проверьте это изображение: cl.ly/image/291f1K2N0V3p В теме ограничений у подпредставлений есть больше, чем просто ограничение по высоте. Проверьте весь список ограничений для этих представлений здесь: cl.ly/image/3l061i123j2i
backslash-f

1
Я все еще не могу заставить работать прокрутку - я заметил, что ваши представления подпредставлений "затенены" в вашем проекте. После некоторого исследования, похоже, это потому, что вы используете «классы размера». Как это влияет на прокрутку? Есть ли способ заставить работать прокрутку без этого?
Андрей К

Кроме того, как вы сделали свой супервизор намного длиннее длины по умолчанию? Я пытаюсь добавить кнопки, которые будут отображаться «ниже сгиба» (или за пределами экрана), но, очевидно, я не могу добавить их в суперпредставление, если не могу перетащить их в суперпредставление, поскольку оно недостаточно велико.
Андрей К

1
после долгого дня поиска и попытки сделать это макет глупости, я нашел этот ответ и работает с первой попытки .. Спасибо, мужик. Вы спасли мой день .. Я хотел бы отдать тысячу голосов за этот ответ ..: )
Бобби Стенли

32

Простой автономный пример

Судя по большому количеству голосов по вопросу и малому количеству голосов за ответы, люди не находят здесь понятного и быстрого решения. Позвольте мне попытаться добавить один. Этот проект является автономным примером, полностью выполненным в Интерфейсном Разработчике. Вы должны быть в состоянии пройти через это через 10 минут или меньше. Затем вы можете применить полученные вами концепции к своему собственному проекту.

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

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

Ключевые идеи

  • UIScrollViewСледует использовать только один подвид. Это «UIView», который служит представлением содержимого для хранения всего, что вы хотите прокрутить.
  • Сделайте так, чтобы представление контента и родитель прокрутки имели одинаковую высоту для горизонтальной прокрутки. (Равная ширина для вертикальной прокрутки)
  • Убедитесь, что весь прокручиваемый контент имеет заданную ширину и закреплен со всех сторон.

Начать новый проект

Это может быть только одно приложение.

Раскадровка

В этом примере мы сделаем горизонтальную прокрутку. Выберите View Controller и затем выберите Freeform в Инспекторе размера. Сделайте ширину 1,000и высоту 300. Это просто дает нам место на раскадровке для добавления контента, который будет прокручиваться.

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

Добавить представление прокрутки

Добавьте UIScrollViewи прикрепите все четыре стороны к корневому виду контроллера представления.

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

Добавить представление содержимого

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

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

Равные высоты

Теперь в Outline документа, Commandщелкните и представление контента и родительское представление представления прокрутки , чтобы выбрать их обоих. Затем установите высоты равными ( Controlперетащите из представления содержимого в представление прокрутки). Это тоже ключ. Поскольку мы прокручиваем горизонтально, представление содержимого представления прокрутки не будет знать, насколько оно должно быть высоко, если мы не установим его таким образом.

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

Примечание:

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

Добавить содержание

Добавьте три UIViewс и дайте им все ограничения. Я использовал 8-балльные поля для всего.

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

Ограничения:

  • Зеленый вид: закрепите верхний, левый и нижний края. Сделай ширину 400.
  • Красный вид: закрепите верхний, левый и нижний края. Сделай ширину 300.
  • Фиолетовый вид: закрепите все четыре края ребер. Сделайте ширину равной оставшемуся месту (в данном случае 268).

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

Законченный

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

Для вертикальной прокрутки просто поменяйте местами все ширины и высоты в этом примере (проверено и работает).

Дальнейшее обучение


9

ContentSize неявно устанавливается путем применения ограничений внутри UIScrollView.

Например, если у вас есть UIScrollView внутри UIView, это будет выглядеть так (как я уверен, вы знаете):

    UIView *containerView               = [[UIView alloc] init];
    UIScrollView *scrollView            = [[UIScrollView alloc] init];
    [containerView addSubview:scrollView];
    containerView.translatesAutoresizingMaskIntoConstraints = NO;
    scrollView.translatesAutoresizingMaskIntoConstraints    = NO;
    NSDictionary *viewsDictionary       = NSDictionaryOfVariableBindings(containerView, scrollView);

    [containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[scrollView]|"
                                                                          options:kNilOptions
                                                                          metrics:nil
                                                                            views:viewsDictionary]];
    [containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[scrollView]|"
                                                                          options:kNilOptions
                                                                          metrics:nil

Это установит scrollView для заполнения размера containerView (таким образом, containerView должен быть определенного размера).

Затем вы можете настроить contentSize для UIScrollView, неявно установив его достаточно большим, чтобы удерживать кнопки следующим образом:

    UIButton *buttonA                   = [[UIButton alloc] init];
    UIButton *buttonB                   = [[UIButton alloc] init];
    UIButton *buttonC                   = [[UIButton alloc] init];
    [scrollView addSubview:buttonA];
    [scrollView addSubview:buttonB];
    [scrollView addSubview:buttonC];
    buttonA.translatesAutoresizingMaskIntoConstraints       = NO;
    buttonB.translatesAutoresizingMaskIntoConstraints       = NO;
    buttonC.translatesAutoresizingMaskIntoConstraints       = NO;

    viewsDictionary                     = NSDictionaryOfVariableBindings(scrollView, buttonA, buttonB, buttonC);

    [scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[buttonA]-|"
                                                                       options:kNilOptions
                                                                       metrics:nil
                                                                         views:viewsDictionary]];
    [scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[buttonA]-[buttonB]-[buttonC]-|"
                                                                       options:NSLayoutFormatAlignAllBaseline
                                                                       metrics:nil
                                                                         views:viewsDictionary]];

Итак, я установил ограничения между scrollView и кнопками, а не containerView и кнопками? Я думаю, что это единственное отличие, которое я занимаюсь спортом между вашим кодом и тем, что я делаю сейчас через раскадровку.
user1459524

Я только после второго чтения понял, что вы настраиваете КОНТЕЙНЕР, а не КОНТЕНТ. Основываясь на вашем коде, я воссоздал все точно в раскадровке, и это не прокрутка. Я отредактирую свой вопрос с некоторыми скриншотами.
user1459524

1
Получается, что моя попытка воссоздать код в раскадровке была не на 100% правильной. Значение для последней кнопки должно быть точно равно нулю, отражая H: | - [buttonA] - [buttonB] - [buttonC] - | что не очень очевидно при работе в раскадровке (или, по крайней мере, не для меня), но теперь после факта кажется тривиальным. Я люблю autolayout, но эти мелочи
помогают вам

То, что упомянул @ user1459524, было проблемой для меня. Мое нижнее представление было кнопкой, и нижнее ограничение было -32 IB. Я установил это в 0, и оно обновилось в IB, чтобы быть Bottom Space для: superview. Это будет работать, и, кажется, пока вы на положительной стороне, это работает. Похоже, что это может быть ошибка с IB. Надеюсь, что это помогает кому-то еще. Я также удалил все виды и переписал их, что помогает при попытке выложить их, которые я нахожу, и обычно это не занимает много времени.
Майкл

8

Существует много вопросов об использовании AutoLayout с UIScrollView, ключевой момент, который мы игнорируем, заключается в том, что внутренние представления UIScrollView накладывают ограничения на представление содержимого, но не на сам UIScrollView. Обратитесь к Технической ноте TN2154 , вы можете найти:

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

На следующем рисунке изображено, что: введите описание изображения здесь

Вы можете найти конечный интервал, равный 500 точкам, если для UIScrollView наложено ограничение, представление будет неправильно размещено, и ему следует обновить свой фрейм. Однако никаких предупреждений и ошибок нет. Потому что все ограничения против представления контента.

UIScrollView рассчитает размер представления содержимого в соответствии с ограничениями внутренних представлений. (Например, размер контента: ширина = 100 (начальный пробел) + 200 (ширина представления) + 500 (задний пробел), высота = 131 (интервал сверху) + 200 (высота) + 269 (интервал снизу)

Как добавить ограничения для представлений в UIScrollView:

  1. Отображение позиций представлений в представлении содержимого.
  2. Добавьте верхний, правый, нижний, левый интервал к краям представления содержимого, а также ширину и высоту этих представлений.

И все это сделано.

Простой способ справиться с AutoLayout с scrollview - добавить контейнерное представление, содержащее все подпредставления в представлении с прокруткой.

Вывод: ключевой момент для понимания AutoLayout с UIScrollView - это внутренние представления, накладывающие ограничения на представление содержимого, но не на сам UIScrollView.

прикрепленный пример кода


5

Следующее решение работало для меня с scrollView с autolayout и без contentSize :

  1. Перетащите n drop scrollView в viewController и примените любые ограничения, чтобы покрыть пространство, которое вы хотите.
  2. Перетащите n, перетащите UIView внутрь scrollView и сделайте так, чтобы он покрывал все пространство scrollView, и примените ограничения к верхнему, левому, правому и нижнему пространству от scrollView.
  3. Установите высоту (и ширину, если требуется горизонтальная прокрутка) внутреннего вида в соответствии с необходимостью прокрутки. Эта часть также может быть выполнена из кода, если требуется.
  4. Critical . После того, как вы установили высоту на какое-то большое значение в точке (3), вернитесь к точке (2) и убедитесь, что верхнее, левое, правое и нижнее значения возвращены к нулю, поскольку Xcode, возможно, изменил их для вас, когда вы заставляете изменил высоту в (3).

И вы сделали. Теперь вы можете добавить любое количество элементов управления в это представление и применить ограничения, относящиеся друг к другу (которые не работают без этого представления). Если вы не хотите использовать это представление, вам придется применять ограничения для каждого элемента управления, связанного с scrollView (не связанного друг с другом).


Подавляющий наконечник ..............

Critical . Допустим, для ясности UIScrollView имеет ширину 1000 и высоту 100. (На самом деле обычно эти значения будут динамическими, конечно, в зависимости от ширины устройства и т. Д. Но пока просто скажем 1000 в ширину и 100 в высоту.) Допустим, вы делаете горизонтальную прокрутку. Так что поместите UIView внутри UIScrollView. (Это «представление содержимого».) Установите все четыре ограничения представления содержимого сверху, снизу, впереди, сзади, в представление прокрутки. Сделайте их все ноль, даже если это кажется неправильным. Установите высоту содержимого UIView равным 100 и забудьте об этом. Теперь: вы хотите прокрутить горизонтально, поэтому установите ширину представления контента, скажем, 1225.

Обратите внимание, что ширина представления содержимого теперь на 225 больше ширины родительского представления прокрутки. Это нормально: на самом деле, вы ДОЛЖНЫ сделать это. Обратите внимание, что

... вы НЕ устанавливаете ширину трейлинга в минус 225 ...

Вы могли бы подумать, что должны «соответствовать» ширине, как обычно . Но если вы это сделаете, это не будет работать вообще.

Вы должны установить начальные и конечные числа в ZERO , никогда не отрицательные (даже если ширина "больше")

Интересно, что на самом деле вы можете установить начальные / конечные числа на любое положительное значение (попробуйте, скажем, «50»), и это дает вам некоторый запас отказов. (Это часто выглядит великолепно: попробуйте.) Любое отрицательное значение на любом конце будет "молча сломаться".

Обратите внимание, что, к сожалению, часто Xcode (по крайней мере, из 7.3.1),

«услужливо» установит для вас эти значения на отрицательные числа!

потому что он пытается автоматически подсчитать их для вас. Если это так, то он молча сломается Установите все четыре значения на ноль в первом случае. И установите ширину просмотра контента намного шире, чем «1000» в примере.


Отредактировано: я закончил с использованием UITableView вместо UIScrollView для большей части моих требований. Поскольку tableView мне кажется гораздо более гибким и динамичным.


Это на самом деле лучший ответ здесь. Спасибо!
Толстяк

4

Я предполагаю, что у вас возникли проблемы с contentSize. Проверьте это сообщение в блоге о том , как обрабатывать contentSizeпри использовании «чистого» AutoLayout подход. Суть в том, что ваши ограничения неявно определяют размер контента. Вы НИКОГДА не устанавливаете это явно при использовании AutoLayout. Я приложил пример проекта в конце поста блога, чтобы продемонстрировать, как он работает


3

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

Вот простой пример. Создайте раскадровку с одним представлением, у которого есть одно представление прокрутки. Установите ограничения вида прокрутки, чтобы он соответствовал размеру представления, в которое вы его поместили.

Внутри этого вида прокрутки добавить один вид. Явно установите размер этого представления, используя ограничения (и убедитесь, что размер больше, чем представление прокрутки).

Теперь добавьте еще четыре ограничения к этому внутреннему виду, фиксируя четыре ребра внутреннего вида к его родительскому виду прокрутки. Эти четыре ограничения приведут к тому, что размер контента увеличится, чтобы вместить внутренний вид.

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


3

Если ваш вопрос «Как поместить кучу UITextFields в UIScrollView с вертикальной прокруткой так, чтобы они переместились с клавиатуры, когда они сфокусированы», лучший ответ:

Не.

Вместо этого используйте UITableViewController со статическими ячейками.

Вы получаете это бесплатное поведение прокрутки, И все вставки контента Просто работайте, если ваш контроллер представления отображается внутри UINavigationController.


3

Вы должны организовать свой макет следующим образом:
ViewControllerViewсодержит ScrollView, ScrollViewсодержит ContainerView, ContainerViewсодержит 2Labels
введите описание изображения здесь

Затем выполните 3 шага для ScrollViewпрокрутки банок

  1. Установочный ScrollViewштифт (верхний / правый / нижний / левый) дляViewControllerView
    • Установочный ContainerViewштифт (верхний / правый / нижний / левый) дляScrollView
    • Установить Horizontally in Container( не установить Vertically in Container)
    • Label1прикрепить ( сверху / справа / слева) кContainerView
    • Label1штифт (вправо / влево / снизу ) , чтобы ContainerViewи сверху , чтобыLabel1

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

ЗДЕСЬ это демонстрационный проект

Надеюсь это поможет


1

Подход с чистым автоматическим размещением работает прекрасно, но довольно сложно настроить его, если вы переходите с неавтоматического размещения. Я сделал это несколько раз, и у меня есть несколько общих советов:

  • Начните с малого: даже если это означает воссоздание представлений раскадровки, начните с нескольких элементов и постепенно создавайте представления, проверяя работоспособность прокрутки после добавления нескольких элементов.
  • Отключите translationsAutoresizingMaskIntoConstraints для всего: это всегда было причиной конфликтов ограничений для меня.
  • Правильно установите ограничения UIScrollView: убедитесь, что представление прокрутки со всех сторон подключено к родительскому представлению, иначе оно просто не будет расширяться вообще.

1

Спустя некоторое время, решив эту проблему, я наконец нашел решение. Я работаю с раскадровками универсальных размеров (600x600). Я создал UIView (contentView) размером с scrollView и создал ограничения для Top, Bottom, Leading и Trailing для scrollView. Затем я обрезал размер contentView вручную до 600x600. Раскадровка перестала пытаться изменить размер всего, и я смог работать, но на реальном устройстве или симуляторе вид выглядел ужасно. Я сделал 2 аутлета с ограничением размеров.

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *contentViewWidthConstraint; 
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *contentViewHeightConstraint;

Тогда в viewDidLoad

CGSize viewSize = self.view.frame.size;
self.contentViewWidthConstraint.constant = viewSize.width;
self.contentViewHeightConstraint.constant = viewSize.height;

Прекрасно работает.


1

Я потратил несколько дней, пытаясь найти решение, как использовать AutoLayout view для встроенного Scrollview, чтобы центрировать scrollview на видимом экране, который работает на всех устройствах / размерах экрана, а также с поворотом экрана.

Я провел дни, пытаясь сделать это только с Autolayout, и приблизился, но никогда не был достаточно близко. В итоге мне пришлось добавить 3 строки кода на экран, в viewDidLoad.

Смотрите решение ниже:

  1. Создайте вид прокрутки и заполните его любыми нужными объектами.
  2. Включить автоматическую разметку
  3. Затем отцентрируйте ScrollView по вертикали и горизонтали Центр ScrollView
  4. Выберите View, а затем «Add пропущенные ограничения» - тогда это сделает свое дело
  5. В результате генерируется много ограничений. Для вида создано 2 новых: «Horiz space scrollview to View» и «Vert space scrollview to view» или наоборот.
  6. Удалите 'Horiz space scrollview to View', чтобы у вас осталось 3 ограничения на просмотр. 2 для ввода прокрутки в представлении и одна для установки вертикального промежутка между прокруткой и представлением
  7. Теперь свяжите ограничение Vert с вашим кодом, нажав Ctrl, перетащив его в файл заголовка и создавая NSLayoutConstraint IBOutlet (я назвал мой constraintVertVtoSV)
  8. Теперь перейдите к файлу .m и добавьте эти строки кода в viewDidLoad (поиграйтесь с количеством отступов, чтобы получить правильное центрирование вертикали)

    if (IPAD)

    {self.constraintVertVtoSV.constant = 150.0; }

  9. теперь он должен работать на всех устройствах, быть правильно отцентрирован и по-прежнему правильно прокручиваться.


1

Если, как и я, вы просто используете статический контент без ограничений внутри подпредставления, как вы можете сделать так:

override func viewDidLayoutSubviews() {
    scrollView.contentSize = CGSizeMake(320, 800)
}

1

Подобная проблема у меня сегодня с iOS 8.4, Xcode 6.4

Есть представление, содержащее представление прокрутки, содержащее представление содержимого (UIView), содержащее подпредставления.

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

Первоначально представление содержимого будет отказываться от размера в качестве полной ширины представления прокрутки. Мне пришлось добавить дополнительное ограничение на представление содержимого, чтобы его ширина соответствовала представлению родительской прокрутки. Или я мог бы установить ограничение contentView.centerX == scrollView.centerX. Любой из них, в дополнение к закреплению краев, внезапно заставил представление контента иметь правильный размер.

// Either one of these additional constraints are required to get autolayout to correctly layout the contentView. Otherwise contentView size is its minimum required size
scrollView.addConstraint(NSLayoutConstraint(item: contentView, attribute: .CenterX, relatedBy: .Equal, toItem: scrollView, attribute: .CenterX, multiplier: 1.0, constant: 0))
scrollView.addConstraint(NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Width, relatedBy: .Equal, toItem: scrollView, attribute: .Width, multiplier: 1.0, constant: 0.0))

Закрепление краев представления содержимого в представлении прокрутки с использованием визуальных ограничений формы,

let cvConstraints = ["H:|[contentView]|", "V:|[contentView]|"]

Я использую процедуру для перебора массива и добавления их в scrollView.


1

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


1

В скором времени вы можете использовать это рабочее решение.

контрсилами

ScrollView: Ведущий, трейлинг, верх, низ = супервизор

ContentView: Leading, Trailing, Top, Bottom = ScrollView. Высота фиксированная / относительно содержимого.

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

extension UIView {

    func setupContentViewForViewWithScroll(contentView vwContent : UIView) {
        //Set constraint for scrollview content
        let constraint = NSLayoutConstraint(item: vwContent, attribute: NSLayoutAttribute.Width, relatedBy: .Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: self.bounds.size.width)
        vwContent.addConstraint(constraint)
        self.layoutSubviews()
    }

}

А в View Controller viewDidLayoutSubviewsя просто вызываю этот метод:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    self.view.setupContentViewForViewWithScroll(contentView: vwContent)
}

0

Я знаю, что это решение непрофессионала, а не то, что Apple предлагает в документе, но оно работало для меня дважды, с другим контентом и может быть настроено очень быстро: в контроллере представления раскадровки вставьте UIView. В UIView вставьте табличное представление, динамическое, 0 ячеек прототипа, стиль простой или сгруппированный. В табличном представлении вставьте представление прокрутки, в представлении прокрутки вставьте содержимое. Вот и все, нет настроек в контроллере пользовательского представления.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.