У меня есть проблемы с AutoLayout в Interface Builder (Xcode 5/iOS 7). Это очень важно и важно, поэтому я думаю, что каждый должен знать, как это работает. Если это ошибка в Xcode, это критический вопрос!
Итак, всякий раз, когда у меня есть иерархия представлений, такая как я сталкиваюсь с проблемами:
>UIViewController
>> UIView
>>>UIScrollView
>>>>UILabel (or any other comparable UIKit Element)
UIScrollView имеет жесткие ограничения, например, 50 пикселей со всех сторон (без проблем). Затем я добавляю ограничение по максимальному пространству в UILabel (без проблем) (и я даже могу выровнять высоту/ширину метки, ничего не меняет, но не должен быть ненужным из-за собственного размера метки)
Проблема возникает, когда я добавляю трейлинг-ограничение в UILabel:
Например, Trailing Space для: Superview Equals: 25
Теперь возникают два предупреждения - и я не понимаю, почему:
A) Масштабируемость прокручиваемого содержимого (просмотр прокрутки имеет неоднозначную прокручиваемую высоту/ширину содержимого)
B) Неверные представления (ожидаемая метка: x = -67 Фактическая: x = 207
Я сделал этот минимальный пример в новом новом проекте, который вы можете скачать, и я прикрепил скриншот. Как вы можете видеть, Interface Builder ожидает, что ярлык будет находиться за пределами границы UIScrollView (оранжевый пунктирный прямоугольник). Обновление рамки Label с помощью инструмента Resolve Issues Tool перемещает ее прямо там.
Обратите внимание: если вы замените UIScrollView на UIView, поведение будет таким, как ожидалось (рамка Label верна и соответствует ограничению). Так что, похоже, проблема с UIScrollView или я упускаю что-то важное.
Когда я запускаю приложение, не обновляя рамку Label, как было предложено IB, он позиционируется просто отлично, где он должен быть, и UIScrollView прокручивается. Если я обновляю фрейм, ярлык скрыт из виду, а UIScrollView не будет прокручиваться.
Помоги мне Оби-Ван Кеноби! Почему неоднозначный макет? Почему неуместное мнение?
Вы можете скачать образец проекта здесь и попробовать, если вы можете выяснить, что происходит: https://github.com/Wirsing84/AutoLayoutProblem
ПРИМЕЧАНИЕ. На iOS> 10.0 это не было проверено; поэтому решение может быть неполным в определенных ситуациях.
Поэтому я просто разобрался в этом:
Внутри UIScrollView
добавьте UIView
(мы можем назвать это contentView
);
В этом contentView
установите верхнее, нижнее, левое и правое поля на 0 (конечно, из scrollView
который является superView
); Установите также выравнивание по горизонтали и по вертикали;
Закончено.
Теперь вы можете добавить все свои представления в этот contentView
, а contentSize
scrollView
будет автоматически изменяться в соответствии с contentView
.
Обновить:
Некоторое частное дело освещено этим видео, опубликованным @Sergio в комментариях ниже.
Эта ошибка заняла у меня некоторое время для отслеживания, изначально я попытался привязать размер ScrollView, но в сообщении об ошибке четко сказано "размер содержимого". Я убедился, что все, что я приколол с вершины ScrollView, также было закреплено на дне. Таким образом ScrollView может вычислить его высоту содержимого, найдя высоту всех объектов и ограничений. Это разрешило неоднозначную высоту контента, ширина очень похожа... Первоначально у меня было большинство вещей X, сосредоточенных в ScrollView, но мне пришлось также привязывать объекты к стороне ScrollView. Мне это не нравится, потому что iPhone6 может иметь более широкий экран, но он удалит ошибку "неоднозначной ширины содержимого".
Ответьте на мой вопрос с ответом UIScrollView + Centered View + Ambigous Scrollable Content Size + много размеров iPhone.
Но он полностью покрывает ваше дело!
Has ambiguous scrollable content width
и Has ambiguous scrollable content height
.
Важно: вам нужно добавить ограничения трейлинг и/или снизу. Не "ведущий и верхний" - он не работает!
Вы можете проверить это в моем примере проекта, демонстрируя, как исправить эту проблему.
P.S.
Согласно логике - это действие должно вызывать "конфликтующие ограничения". Но нет!
Я не знаю, почему это работает и как Xcode обнаруживает, какое ограничение более приоритетно (потому что я не задал приоритет для этих ограничений). Я буду благодарен, если кто-нибудь объяснит, почему он работает в комментариях ниже.
Вам необходимо создать UIView
как UIView
UIScrollView
как описано ниже:
UIViewController
UIView
'Главный вид' UIScrollView
UIView
'Вид контейнера' Вторым шагом является создание ограничений UIScrollView
. Я сделал это с верхним, нижним, ведущим и конечным ограничениями для его superView.
Затем я добавил ограничения для контейнера UIScrollView
и вот здесь начинается проблема. Когда вы накладываете те же ограничения (сверху, снизу, впереди и сзади), раскадровка выдает предупреждение:
"Имеет неоднозначную ширину прокручиваемого содержимого" и "Имеет неоднозначную высоту прокручиваемого содержимого"
Продолжайте использовать те же ограничения, что и выше, и просто добавьте ограничения " Equal Height
и " Equal Width
к своему представлению контейнера по отношению к основному представлению, а не к вашему UIScrollView
. Другими словами, ограничения Контейнерного Представления связаны с UIScrollView
.
После этого у вас не будет предупреждений в раскадровке, и вы сможете продолжить добавлять ограничения для ваших подпредставлений.
Я наконец понял это, я надеюсь, что это легче понять.
Вы часто можете обойти это предупреждение, добавив базовый UIView в представление прокрутки как "представление контента", как они упоминали, и сделайте его таким же размером, как и представление прокрутки, и в этом представлении содержимого задайте эти 6 параметров.
Как видите, вам нужно всего 6 параметров! Что... при нормальных обстоятельствах вы дублируете 2 ограничения, но это способ избежать этой ошибки раскадровки.
iOS 12, Swift 4
Самый простой способ с помощью autolayout
:
UIScrollView
и прикрепите его 0,0,0,0
к 0,0,0,0
(или желаемому размеру)UIView
в ScrollView, прикрепите его 0,0,0,0
ко всем 4 сторонам и 0,0,0,0
по horizontally
и vertically
.bottom
и align center Y
приоритет по align center Y
на 250. (для горизонтальной прокрутки измените trailing
и align center X
)Я знаю, что могу опоздать, но следующее решение решает такие проблемы без дополнительного кода, просто используя раскадровки:
Для просмотра содержимого вам нужно установить ограничения для ведущих/конечных/верхних/нижних пробелов для прокрутки и , это не изменит рамки представления контента, например:
Конечно, вам нужно создать дополнительные ограничения для представления контента, чтобы просмотреть прокрутку можно узнать размер содержимого. Например, установите фиксированную высоту и центр x.
Надеюсь, что это поможет.
Посмотрите на это очень быстро и на точечный учебник о том, как заставить просмотр прокрутки работать и полностью прокручиваться с автоматической компоновкой. Теперь единственное, что все еще оставляет меня озадаченным, - это то, почему размер содержимого прокрутки всегда больше, чем необходимо..
http://samwize.com/2014/03/14/how-to-use-uiscrollview-with-autolayout/
Для меня добавление contentView
действительно не срабатывало, как было предложено. Более того, он создает накладные расходы из-за добавленного представления (хотя я не считаю это большой проблемой). Для меня лучше всего было отключить проверку двусмысленности для моего scrollView
. Все складывается красиво, поэтому я думаю, что все в порядке, как у меня. Но имейте в виду, что если другие ограничения для вашего scrollView
ломаются, Interface-Builder больше не будет предупреждать вас об этом.
См. ниже: просмотр содержимого в вертикальном и горизонтальном централизованном просмотре. вы получили ошибку двусмысленности, всегда убедитесь, что два добавленных в scrollview из вашего представления содержимого: 1).button space to container.2) конечное пространство для ограничения, выделенное на снимке экрана,
эти средства ограничения в прокрутке - это сколько вы можете прокручивать после высоты или ширины представления контента.
это может помочь вам.
Люди, которые борется с uiscrollview, а не прокруткой, просто ограничивают ограничение нижнего уровня содержимого своим последним макетом представления (который находится внутри вашего содержимого). Не забудьте удалить ограничение центра Y.
Откажитесь от всех ограничений, указанных выше. Scrollview беспокоится только о том, чтобы получить максимальную высоту от представления содержимого, и мы устанавливаем его как последнее ограничение нижнего вида, что означает, что scrollview автоматически изменит его смещение содержимого.
В моем случае последний просмотр был UILable без свойства lines = 0 (который автоматически регулирует его высоту в зависимости от его содержимого), поэтому он динамически увеличивает высоту uilable и, в конечном счете, нашу прокручиваемую область увеличивается из-за того, что макет uilable bottom выравнивается с нашим контентом снизу, что заставляет scrollview увеличивать его смещение содержимого.
@Matteo Gobbi отвечает, но в моем случае прокрутка не может прокручиваться, я удаляю " центр выравнивания Y" и добавляю " высотa >= 1", scrollview станет прокручиваемым
Я решил эту проблему для своего взгляда, используя "Разрешить автоматические макеты"> "Добавить отсутствующие ограничения" для Selected View
Следующие две проблемы решают мою проблему:
trailing = Stack View.trailing - 10
bottom = Stack View.bottom + 76
в котором: trailing, bottom - конечная нижняя часть UIScrollView
Это техническое примечание полезно.
pure auto layout approach
, упомянутый в статье, также может быть выполнен в конструкторе интерфейса.
Я сделал видео на youTube
Прокрутить StackViews, используя только Storyboard в Xcode
Я думаю, что здесь могут появиться 2 сценария.
Вид внутри scrollView -
UIView
)UIStackView
)Для просмотра с вертикальной прокруткой в обоих случаях вам необходимо добавить эти ограничения:
4 ограничения сверху, слева, снизу и справа.
Равная ширина для прокрутки (для остановки прокрутки по горизонтали)
Вам не нужны никакие другие ограничения для представлений, у которых есть собственная внутренняя высота содержимого.
Для представлений, которые не имеют высоты встроенного содержимого, вам необходимо добавить ограничение высоты. Вид будет прокручиваться только в том случае, если ограничение высоты больше высоты прокрутки.
Используя contentView (UView
) в качестве контейнера внутри UIScrollView
, прилипают к краям (top
, bottom
, trailing
, leading
) из надтаблицы (UIScrollView
) и contentView
должны иметь equalwidth
и equalheight
к надтаблице. Это ограничения. И вызов метода:
-(void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
self.scrollView.contentSize = self.contentView.frame.size;
}
Решенные проблемы для меня.
Быстрый подход 4+:
1) Установите UIScrollView верхний, нижний, левый и правый поля на 0
2) Внутри UIScrollView добавьте UIView и установите верхние, нижние, ведущие, конечные поля равными 0 (равным полям UIScrollView).
3) Наиболее важной частью является установка ширины и высоты, где ограничение по высоте должно иметь низкий приоритет.
private func setupConstraints() {
// Constraints for scrollView
scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
// Constraints for containerView
containerView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
containerView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
containerView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
containerView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
containerView.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true
let heightConstraint = containerView.heightAnchor.constraint(equalTo: scrollView.heightAnchor)
heightConstraint.priority = UILayoutPriority(rawValue: 250)
heightConstraint.isActive = true
}
Установите ViewController (тот, у которого есть UIScrollView) размер Freeform в инспекторе размеров в Interface Builder, и все должно работать.
Настройка свободной формы в инспекторе размеров в Interface Builder для содержащего UIViewcontroller
Вам просто нужно убедиться, что есть способ сделать непрерывный строка ограничений сверху вниз от scrollview. [-X-Х-Х]
В моем случае - прокручивание по горизонтали прокрутки - мне также нужно было добавить ограничения ширины и высоты для каждого дочернего элемента прокрутки, хотя Техническая нота Apple не говорит вам об этом.
Как уже упоминалось в предыдущих ответах, вы должны добавить пользовательский вид внутри прокрутки:
Добавьте все ваши подпрограммы в представление содержимого. В какой-то момент вы увидите, что просмотр содержимого прокрутки имеет предупреждение неоднозначного размера содержимого, вы должны выбрать представление контента и нажать кнопку "Разрешить авто макет" (в нижнем правом углу макета IB) и выбрать "Добавить отсутствующий ограничений".
С этого момента, когда вы запускаете проект, прокрутка автоматически обновит его размер содержимого, не потребуется дополнительный код.
Если кто-то получает поведение, когда вы замечаете полосу прокрутки в правом прокрутке, но содержимое не перемещается, этот факт, вероятно, стоит рассмотреть:
Вы также можете использовать ограничения между содержимым представлений прокрутки и объектами вне прокрутки, чтобы обеспечить фиксированную позицию для содержимого прокрутки, чтобы содержимое отображалось в виде прокрутки.
Что от Apple documentation. Например, если вы случайно привязали свой верхний ярлык /Button/Img/View к виду вне области прокрутки (может быть, заголовок или что-то еще выше scrollView?) Вместо contentView, вы бы заморозили весь контентный просмотр на месте.
[проверено в XCode 7.2 и для iOS 9.2]
Что подавляло ошибки и предупреждения Storyboard для меня, это установить собственный размер прокрутки и представление содержимого (в моем случае, stackview) для Placeholder. Этот параметр можно найти в инспекторе размера в раскадровке. И в нем говорится: настройка размера внутреннего содержимого времени разработки влияет только на представление при редактировании в Interface Builder. У представления не будет такого внутреннего размера содержимого во время выполнения.
Итак, я думаю, мы не ошибаемся, установив это.
Примечание. В раскадровке я привязал все края scrollview к супервизу и всем краям stackview к scrollview. В моем коде я установил translatesAutoresizingMaskIntoConstraints как false как для scrollview, так и для stackview. И я не упомянул о размере контента. Когда стековый просмотр растет динамически, ограничения, установленные в раскадровке, гарантируют, что стек прокручивается.
Предупреждение о раскадровке сводило меня с ума, и я не хотел сосредотачивать вещи горизонтально или вертикально, чтобы подавить предупреждение.
Я получал ту же ошибку. Я сделал следующее
Теперь добавьте начало/конец/верх/низ для scrollView (2), затем UIView (3).
Выберите "Вид" (1) и "Вид" (3), заданный одинаково по высоте и весу. Он решил мою проблему.
Я сделал видео, которое поможет:
То, что я сделал, это создать отдельный просмотр содержимого, как показано здесь.
Представление контента является свободной формой и может содержать все дочерние элементы с их собственными ограничениями в отношении contentView.
UIScrollView добавляется в основной контроллер представления.
Программно я добавляю contentView, который связан через IBOutlet с классом и задает contentView UIScrollView.
Я думаю, что это 10-секундная работа. Я заметил это в XCode 7.3 и сделал видео на нем. Проверьте здесь:
https://www.youtube.com/watch?v=yETZKqdaPiI
Все, что вам нужно сделать, добавьте subview к UIScrollView
с одинаковой шириной и высотой. Затем выберите ViewController и нажмите Reset to suggested constraint
. Пожалуйста, проверьте видео для четкого понимания.
Спасибо
все подзоны внутри прокрутки должны иметь ограничения, затрагивающие все края прокрутки, как объясняется в документации, высота и ширина прокрутки автоматически вычисляются с помощью мер в подзонах, это означает, что вы необходимо иметь Trailing и ведущие ограничения для ширины и верхних и нижних ограничений для высоты.