Подтвердить что ты не робот

UIScrollView Прокручиваемый размер содержимого Неоднозначность

У меня есть проблемы с 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

Illustration of the problem in Interface Builder

4b9b3361

Ответ 1

Так что я просто разобрался следующим образом:

  1. Внутри UIScrollView добавьте a UIView (мы можем назвать это contentView);

  2. В этом contentView установите верхнее, нижнее, левое и правое поля равными 0 (конечно, из scrollView, который является superView); Установите также выравнивание по центру по горизонтали и вертикали;

Закончено.

Теперь вы можете добавить все свои виды в этот contentView, и размер contentSize в scrollView будет автоматически изменен в соответствии с contentView.

Обновление:

Этот особый случай описан в этом видео, опубликованном @Sergio в комментариях ниже.

Ответ 2

Эта ошибка заняла у меня некоторое время для отслеживания, изначально я попытался привязать размер ScrollView, но в сообщении об ошибке четко сказано "размер содержимого". Я убедился, что все, что я приколол с вершины ScrollView, также было закреплено на дне. Таким образом ScrollView может вычислить его высоту содержимого, найдя высоту всех объектов и ограничений. Это разрешило неоднозначную высоту контента, ширина очень похожа... Первоначально у меня было большинство вещей X, сосредоточенных в ScrollView, но мне пришлось также привязывать объекты к стороне ScrollView. Мне это не нравится, потому что iPhone6 ​​может иметь более широкий экран, но он удалит ошибку "неоднозначной ширины содержимого".

Ответ 3

Ответьте на мой вопрос с ответом UIScrollView + Centered View + Ambigous Scrollable Content Size + много размеров iPhone.

Но он полностью покрывает ваше дело!

Итак, вот начальное состояние для простейшего случая:

  • scrollView с 0 ограничениями для всех ребер
  • Кнопка с центрированным горизонтальным и вертикальным с фиксированными ограничениями ширины и высоты
  • И, конечно, раздражающие предупреждения Has ambiguous scrollable content width и Has ambiguous scrollable content height.

1

Все, что нам нужно сделать:

  • Добавьте 2 дополнительных ограничения, например "0" для трейлинг и/или нижнего пространства для нашего представления (см. пример на скриншоте ниже).

Важно: вам нужно добавить ограничения трейлинг и/или снизу. Не "ведущий и верхний" - он не работает!

2

Вы можете проверить это в моем примере проекта, демонстрируя, как исправить эту проблему.

P.S.

Согласно логике - это действие должно вызывать "конфликтующие ограничения". Но нет!

Я не знаю, почему это работает и как Xcode обнаруживает, какое ограничение более приоритетно (потому что я не задал приоритет для этих ограничений). Я буду благодарен, если кто-нибудь объяснит, почему он работает в комментариях ниже.

Ответ 4

Вам необходимо создать UIView как UIView UIScrollView как описано ниже:

  • UIViewController
  • UIView 'Главный вид'
    • UIScrollView
      • UIView 'Вид контейнера'
        • [Ваш контент]

Вторым шагом является создание ограничений UIScrollView. Я сделал это с верхним, нижним, ведущим и конечным ограничениями для его superView.

Затем я добавил ограничения для контейнера UIScrollView и вот здесь начинается проблема. Когда вы накладываете те же ограничения (сверху, снизу, впереди и сзади), раскадровка выдает предупреждение:

"Имеет неоднозначную ширину прокручиваемого содержимого" и "Имеет неоднозначную высоту прокручиваемого содержимого"

Продолжайте использовать те же ограничения, что и выше, и просто добавьте ограничения " Equal Height и " Equal Width к своему представлению контейнера по отношению к основному представлению, а не к вашему UIScrollView. Другими словами, ограничения Контейнерного Представления связаны с UIScrollView.

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

Ответ 5

iOS 10+, Swift 4/Swift 5

Самый простой способ, используя autolayout:

  1. Добавьте UIScrollView и прикрепите его 0,0,0,0 к суперпредставлению (или желаемому размеру)
  2. Добавьте UIView в ScrollView, прикрепите его 0,0,0,0 ко всем 4 сторонам и отцентрируйте его horizontally и vertically.
  3. В инспекторе размеров измените приоритет bottom и align center Y на 250. (для изменения горизонтальной прокрутки trailing и align center X)
  4. Добавьте все представления, которые вам нужны, в это представление. Не забудьте установить нижнее ограничение для самого нижнего вида.

Ответ 6

Я наконец понял это, я надеюсь, что это легче понять.

Вы часто можете обойти это предупреждение, добавив базовый UIView в представление прокрутки как "представление контента", как они упоминали, и сделайте его таким же размером, как и представление прокрутки, и в этом представлении содержимого задайте эти 6 параметров.

enter image description here

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

Ответ 7

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

Для просмотра содержимого вам нужно установить ограничения для ведущих/конечных/верхних/нижних пробелов для прокрутки и , это не изменит рамки представления контента, например: enter image description here

Конечно, вам нужно создать дополнительные ограничения для представления контента, чтобы просмотреть прокрутку можно узнать размер содержимого. Например, установите фиксированную высоту и центр x.

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

Ответ 8

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

http://samwize.com/2014/03/14/how-to-use-uiscrollview-with-autolayout/

Ответ 9

См. ниже: просмотр содержимого в вертикальном и горизонтальном централизованном просмотре. вы получили ошибку двусмысленности, всегда убедитесь, что два добавленных в scrollview из вашего представления содержимого: 1).button space to container.2) конечное пространство для ограничения, выделенное на снимке экрана,

эти средства ограничения в прокрутке - это сколько вы можете прокручивать после высоты или ширины представления контента.

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

это может помочь вам.

Ответ 10

Я решил эту проблему для своего взгляда, используя "Разрешить автоматические макеты"> "Добавить отсутствующие ограничения" для Selected View enter image description here

Следующие две проблемы решают мою проблему:

trailing = Stack View.trailing - 10
bottom = Stack View.bottom + 76

в котором: trailing, bottom - конечная нижняя часть UIScrollView

Ответ 11

Используя contentView (UView) в качестве контейнера внутри UIScrollView, прилипают к краям (top, bottom, trailing, leading) из надтаблицы (UIScrollView) и contentView должны иметь equalwidth и equalheight к надтаблице. Это ограничения. И вызов метода:

-(void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    self.scrollView.contentSize = self.contentView.frame.size;
}

Решенные проблемы для меня.

Ответ 12

@Matteo Gobbi отвечает, но в моем случае прокрутка не может прокручиваться, я удаляю " центр выравнивания Y" и добавляю " высотa >= 1", scrollview станет прокручиваемым

Ответ 13

Для меня добавление contentView действительно не срабатывало, как было предложено. Более того, он создает накладные расходы из-за добавленного представления (хотя я не считаю это большой проблемой). Для меня лучше всего было отключить проверку двусмысленности для моего scrollView. Все складывается красиво, поэтому я думаю, что все в порядке, как у меня. Но имейте в виду, что если другие ограничения для вашего scrollView ломаются, Interface-Builder больше не будет предупреждать вас об этом.

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

Ответ 14

Люди, которые борется с uiscrollview, а не прокруткой, просто ограничивают ограничение нижнего уровня содержимого своим последним макетом представления (который находится внутри вашего содержимого). Не забудьте удалить ограничение центра Y.

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

В моем случае последний просмотр был UILable без свойства lines = 0 (который автоматически регулирует его высоту в зависимости от его содержимого), поэтому он динамически увеличивает высоту uilable и, в конечном счете, нашу прокручиваемую область увеличивается из-за того, что макет uilable bottom выравнивается с нашим контентом снизу, что заставляет scrollview увеличивать его смещение содержимого.

Ответ 15

Я сделал видео на youTube
Прокрутить StackViews, используя только Storyboard в Xcode

Я думаю, что здесь могут появиться 2 сценария.

Вид внутри scrollView -

  • не имеет никакого внутреннего содержимого. Размер (например, UIView)
  • имеет собственное внутреннее содержимое. Размер (например, UIStackView)

Для просмотра с вертикальной прокруткой в ​​обоих случаях вам необходимо добавить эти ограничения:

  • 4 ограничения сверху, слева, снизу и справа.

  • Равная ширина для прокрутки (для остановки прокрутки по горизонтали)

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

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


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

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

Ответ 16

Быстрый подход 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
}

Ответ 18

Вертикальная прокрутка

  1. Добавьте UIScrollView с ограничениями 0,0,0,0 для суперпредставления.
  2. Добавьте UIView в ScrollView с ограничениями 0,0,0,0 для суперпредставления.
  3. Добавьте такое же ограничение ширины для UIView в UIScrollView.
  4. Добавьте высоту в UIView.
  5. Добавьте элементы с ограничениями в UIView.
  6. Для элемента, ближайшего к нижней части, убедитесь, что он имеет ограничение к нижней части UIView.

Ответ 19

import UIKit

class ViewController: UIViewController {

    //
    let scrollView: UIScrollView = {

        let sv = UIScrollView()
        sv.translatesAutoresizingMaskIntoConstraints = false
        return sv
    }()

    let lipsumLbl: UILabel = { // you can use here any of your subview

        let lbl = UILabel()
        lbl.translatesAutoresizingMaskIntoConstraints = false
        lbl.text = """
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce eleifend nisi sit amet mi aliquet, ut efficitur risus pellentesque. Phasellus nulla justo, scelerisque ut libero id, aliquet ullamcorper lectus. Integer id iaculis nibh. Duis feugiat mi vitae magna tincidunt, vitae consequat dui tempor. Donec blandit urna nec urna volutpat, sit amet sagittis massa fringilla. Pellentesque luctus erat nec dui luctus, sed maximus urna fermentum. Nullam purus nibh, cursus vel ex nec, pulvinar lobortis leo. Proin ac libero rhoncus, bibendum lorem sed, congue sapien. Donec commodo, est non mollis malesuada, nisi massa tempus ipsum, a varius quam lorem vitae nunc.

        Cras scelerisque nisi dolor, in gravida ex ornare a. Interdum et malesuada fames ac ante ipsum primis in faucibus. Maecenas vitae nisl id erat sollicitudin accumsan sit amet viverra sapien. Etiam scelerisque vulputate ante. Donec magna nibh, pharetra sed pretium ac, feugiat sit amet mi. Vestibulum in ipsum vitae dui vehicula pulvinar eget ut lectus. Fusce sagittis a elit ac elementum. Fusce iaculis nunc odio, at fermentum dolor varius et. Suspendisse consectetur congue massa non gravida. Sed id elit vitae nulla aliquam euismod. Pellentesque accumsan risus dolor, eu cursus nibh semper id.

        Vestibulum vel tortor tellus. Suspendisse potenti. Pellentesque id sapien eu augue placerat dictum. Fusce tempus ligula at diam lacinia congue in ut metus. Maecenas volutpat tellus in tellus maximus imperdiet. Integer dignissim condimentum lorem, id luctus nisi maximus at. Nulla pretium, est sit amet mollis eleifend, tellus nulla viverra dolor, ac feugiat massa risus a lectus. Pellentesque ut pulvinar urna, blandit gravida ipsum. Nullam volutpat arcu nec fringilla auctor. Integer egestas enim commodo, faucibus neque ac, rutrum magna. Vivamus tincidunt rutrum auctor. Cras at rutrum felis. Fusce elementum lorem ut pharetra venenatis.
        """
        lbl.textColor = .darkGray
        lbl.font = UIFont.systemFont(ofSize: 16)
        lbl.numberOfLines = 0
        return lbl
    }()

    //======================================================================//
    //
    // MARK:- viewDidLoad
    //
    override func viewDidLoad() {
        super.viewDidLoad()

        setupViews()
        setupAutoLayout()
    }

    func setupViews() {

        title = "ScrollView Demo"
        view.backgroundColor = .white
        view.addSubview(scrollView)
        scrollView.addSubview(lipsumLbl)
    }

    func setupAutoLayout() {

        scrollView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
        scrollView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
        scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true

        lipsumLbl.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
        lipsumLbl.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
        lipsumLbl.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
        lipsumLbl.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
        lipsumLbl.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
    }
}

Выход:

enter image description here

Ответ 20

То, что я сделал, это создать отдельный просмотр содержимого, как показано здесь.

Представление контента является свободной формой и может содержать все дочерние элементы с их собственными ограничениями в отношении contentView.

UIScrollView добавляется в основной контроллер представления.

Программно я добавляю contentView, который связан через IBOutlet с классом и задает contentView UIScrollView.

UIScrollView with ContentView via Interface Builder

Ответ 21

Я получал ту же ошибку. Я сделал следующее

  • Вид (SuperView)
  • ScrollView 0,0,600,600
  • UIView внутри ScrollView: 0,0,600,600
  • UIView содержит изображение, метку

Теперь добавьте начало/конец/верх/низ для scrollView (2), затем UIView (3).

Выберите "Вид" (1) и "Вид" (3), заданный одинаково по высоте и весу. Он решил мою проблему.

Я сделал видео, которое поможет:

https://www.youtube.com/watch?v=s-CPN3xZS1A

Ответ 22

[проверено в XCode 7.2 и для iOS 9.2]

Что подавляло ошибки и предупреждения Storyboard для меня, это установить собственный размер прокрутки и представление содержимого (в моем случае, stackview) для Placeholder. Этот параметр можно найти в инспекторе размера в раскадровке. И в нем говорится: настройка размера внутреннего содержимого времени разработки влияет только на представление при редактировании в Interface Builder. У представления не будет такого внутреннего размера содержимого во время выполнения.

Итак, я думаю, мы не ошибаемся, установив это.

Примечание. В раскадровке я привязал все края scrollview к супервизу и всем краям stackview к scrollview. В моем коде я установил translatesAutoresizingMaskIntoConstraints как false как для scrollview, так и для stackview. И я не упомянул о размере контента. Когда стековый просмотр растет динамически, ограничения, установленные в раскадровке, гарантируют, что стек прокручивается.

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

Ответ 23

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

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

Что от Apple documentation. Например, если вы случайно привязали свой верхний ярлык /Button/Img/View к виду вне области прокрутки (может быть, заголовок или что-то еще выше scrollView?) Вместо contentView, вы бы заморозили весь контентный просмотр на месте.

Ответ 24

Как уже упоминалось в предыдущих ответах, вы должны добавить пользовательский вид внутри прокрутки:

Пользовательский вид - это ContentView, помеченный на изображении

Добавьте все ваши подпрограммы в представление содержимого. В какой-то момент вы увидите, что просмотр содержимого прокрутки имеет предупреждение неоднозначного размера содержимого, вы должны выбрать представление контента и нажать кнопку "Разрешить авто макет" (в нижнем правом углу макета IB) и выбрать "Добавить отсутствующий ограничений".

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

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

Ответ 25

Вам просто нужно убедиться, что есть способ сделать непрерывный строка ограничений сверху вниз от scrollview. [-X-Х-Х]

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

Ответ 27

Xcode 11+, Swift 5

Если вам интересно, почему все ответы больше не работают, убедитесь, что вы прикрепили представление контента (то, которое вы поместили в представление прокрутки) в Руководство по макету содержимого представления прокрутки и НЕ в рамку Руководство по верстке.

Края представления содержимого (передний, задний, верхний, нижний) не должны быть закреплены как ведущие на изображении - к руководству по компоновке кадров

Not like this

но вот так - к Content Layout Guide.

Select Content Layout Guide from dropdown

enter image description here

И тогда большинство ответов будет работать для вас.

Самый простой подход сейчас выглядит следующим образом:

  1. Поместить вид прокрутки в корневой вид
  2. Прикрепите все стороны вида прокрутки к суперпредставлению
  3. Возьмите другой UIView (назовем его представлением содержимого) и поместите его в представление с прокруткой
  4. Прикрепите все стороны представления содержимого, чтобы прокрутить представление. Руководство по макету содержимого
  5. Прикрепите ширину представления содержимого так, чтобы она соответствовала виду прокрутки. Руководство по компоновке кадра
  6. Фиксируйте высоту представления содержимого любым удобным вам способом (я использовал только ограничение постоянной высоты в приведенном ниже примере)

В целом ваша структура в простейшей реализации будет выглядеть следующим образом

enter image description here

Ответ 28

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

Ответ 29

Я думаю, что это 10-секундная работа. Я заметил это в XCode 7.3 и сделал видео на нем. Проверьте здесь:

https://www.youtube.com/watch?v=yETZKqdaPiI

Все, что вам нужно сделать, добавьте subview к UIScrollView с одинаковой шириной и высотой. Затем выберите ViewController и нажмите Reset to suggested constraint. Пожалуйста, проверьте видео для четкого понимания.

Спасибо