как использовать UIScrollView в Интерфейсном Разработчике?

95

Пока я использовал UIScrollView в прошлом успешно его, манипулируя им программно, у меня возникли проблемы с его работой, настроив его исключительно в Interface Builder.

У меня в приложении для iPhone есть простая страница "О себе". В нем есть UITextViewнесколько значков и ссылки на другие мои приложения. Я добавил все эти представления в свой UIScrollView, расположив их так, чтобы их общий размер был> 480. Когда я запускаю свое приложение, в режиме прокрутки отображается только то содержимое, которое умещается на экране, и ничего не прокручивается.

Можно ли сделать это полностью через IB, или я должен управлять contentSize через код?

Джордж Армхолд
источник

Ответы:

130

Вы забыли установить свойство contentSize для UIScrollView. Как ни странно, вы не можете сделать это из Interface Builder. Вам нужно будет сделать это из контроллера представления, управляющего этим представлением прокрутки.

Стефан Арентц
источник
42
Вау, это делает IB довольно бессмысленным ... Это сработало, спасибо.
Джордж Армхолд
20
Вы можете создать подкласс UIScrollvView, который проверяет, есть ли только одно подпредставление в точке (0,0), а затем автоматически устанавливает contentSize на основе этого подпредставления.
Stefan Arentz
1
Это лучший совет, который я получил за последнее время. Я не мог понять, почему мой режим прокрутки не работал, и не нашел этой информации о contentSize где-либо еще. Спасибо.
Drew C
46
Я пытался выяснить, как установить contentSize в Interface Builder, и нашел это обсуждение. По крайней мере, для меня в Xcode 4.5 я могу установить его, используя «Пользовательские атрибуты времени выполнения», добавив запись с именем contentSizeтипа Sizeи установив желаемое значение.
nlogax 03
5
Я все еще озадачен тем, почему iOS не просто автоматически устанавливает contentSizeвид прокрутки на основе размеров его подвидов , по крайней мере, как поведение по умолчанию.
aroth
113

Ответ Boby_Wan заставил меня задуматься, и я нашел следующее решение для настройки размера содержимого UIScrollView из Interface Builder:

  1. Выберите UIScrollViewв сцене раскадровки
  2. Перейдите в Инспектор идентичности , создайте новый определяемый пользователем атрибут времени выполнения (нажмите кнопку +)
  3. Измените атрибут Key Path наcontentSize
  4. Измените Тип атрибута наSize
  5. Теперь установите значение { желаемая ширина содержимого , желаемая высота содержимого }

например, установка значения на {320, 920} позволит пользователю прокрутить вниз весь дополнительный экран на iPhone.

(Я использую xcode 4.3.3, цель развертывания iOS проекта - 5.1)

Когда я впервые сделал это, я получил следующую ошибку:

Недопустимая конфигурация:
     определяемые пользователем атрибуты времени выполнения типа размера с версиями Xcode до 4.3
     MainStoryboard.storyboard

Если вы тоже получаете эту ошибку, ее легко исправить: выберите раскадровку в навигаторе проекта и откройте инспектор файлов . Найдите / разверните раздел документа Interface Builder , там есть раскрывающийся список для разработки . Убедитесь, что это установлено наXcode 4.3

Herr Grumps
источник
7
Шикарная находка! PS: Я ошеломлен тем, что это лучшее, что могла сделать Apple. Думаю, это показывает, что даже сотрудники Apple никогда не используют свой собственный инструмент (конструктор интерфейсов) :).
Adam
Великолепно, это только что сработало для меня в Xcode 4.4. Но как теперь разместить кнопки в той части прокрутки, которую я не могу «видеть» в IB?
Роберт Аткинс
1
Я только что решил - вам нужно отпустить перетаскивание, когда указатель все еще находится внутри «экрана», иначе он вернется к тому моменту, когда вы начали с. Вот это боль.
Роберт Аткинс
Я пробовал, но получаю сообщение об ошибке, не "this class is not key value coding-compliant for the key keyPath"могли бы вы помочь мне, что я делаю не так? обратите внимание, что я использую xamarin-ios-c #
SoftSan
25

С помощью Autolayout (iOS6 +) вы можете избежать установки contentSize. Вместо этого установите следующие ограничения:

  1. Прикрепите верхнюю часть прокрутки к верхней части его самого верхнего дочернего элемента.
  2. И прикрепите нижнюю часть к низу самого нижнего ребенка.
Даньял Айтекин
источник
1
Спасибо - настройка contentSizeне работает с Xcode 5 и iOS 7
colincameron
18

Вы можете сделать это, используя только Interface Builder, перейдите в Identity Inspector (третья вкладка инспектора) и добавьте новый пользовательский атрибут Runtime с

  • Ключевой путь: contentSize
  • Тип: Размер
  • Значение: {ширина, высота}
Антон Банчев
источник
14

Теперь есть способ сделать UIScrollViewпрокрутку, не выходя из раскадровки :

  1. Выберите UIScrollViewв раскадровке, перейдите в Инспектор размеров и измените нижнее значение (или любое другое значение, которое вам нужно изменить) во вкладках содержимого. » на высоту области содержимого.
  2. Теперь перейдите в Инспектор идентичности и создайте новый определяемый пользователем атрибут времени выполнения (нажав кнопку +) и назовите его contentSize. Неважно, какой тип или значение вы вводите (вы даже можете оставить их значение по умолчанию).

Это заставит UIScrollViewработать нормально, хотя я не знаю, зачем нужен второй шаг (узнал случайно). :(

РоберРМ
источник
Измените значение Bottom на какое?
zakdances
Измените его на высоту области содержимого. Кажется, это работает и отменяет значение, которое вы указываете для определенного пользователем атрибута «contentSize».
Рид Эллис
Да, Рейд, вы правы: вам следует изменить значение Bottom на высоту области содержимого. Я отредактировал свой исходный пост, чтобы отразить это. Спасибо!
RoberRM
4

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

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

в представлении, в котором вы хотите, чтобы оно отображалось в scrollview, поместите простой UIView, который вы используете в качестве заполнителя. (это просто для того, чтобы вы могли визуально спроектировать его местоположение. Если вы просто используете все представление, вы можете пропустить этот шаг и использовать второй фрагмент кода, который я предоставил в конце этого ответа).

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

во время выполнения, в - (void) viewDidLoad

scrollView.contentSize = scrollView.frame.size;
scrollView.frame = placeholder.frame;
[placeholder.superview addSubView:scrollView];
[placeholder removeFromSuperview];

в качестве альтернативы (если вы не использовали заполнитель):

CGRect f = self.view.frame;
scrollView.contentSize = f.size;
f.origin.x = 0;
f.origin.y = 0;
scrollView.frame = f;
[self.view addSubView:scrollView];

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

несинхронизированный
источник
1
Спасибо, это сработало. Также необходимо объявить IBOutlets в YourViewController.h для представлений-заполнителей и прокрутки и подключить их в Interface Builder. И, наконец, точка.notation не была оценена xCode для 3-й строки, поэтому использовался обычный синтаксис отправки сообщений - тогда все работало отлично!
jiy
не беспокойся. При публикации фрагментов кода всегда есть опасность, что некоторые люди не смогут использовать их для понимания концепции, вместо того, чтобы ожидать, что «точный» код будет работать в любой ситуации.
несинхронизировано
Я действительно использую этот метод. Мне вообще не нужно изменять размер этой программы. Я думаю, что так и задумано. Это единственный верный ответ.
user4951 06
Нарисовав его снаружи, я просто переведу его в супер-вид. Тада.
user4951 06
На самом деле я начал использовать проектирование некоторых видов вне сцены для блокнотов, и это значительно упрощает жизнь в некоторых ситуациях, даже не связанных с этой. Спасибо за этот ответ.
Benjamin
4

В Xcode 4.5 с использованием Autolayout у меня нет раздела Content Insets в моем инспекторе размеров. Поэтому мне пришлось добавить его в пользовательские атрибуты времени выполнения, и тогда он работал нормально.

В «Пользовательские атрибуты времени выполнения» вы добавляете keyPath == contentInset типа «Rect» (UIEdgeInsets, который имеет тот же ввод, что и Rect) и определяется как {top, left}, {bottom, right}. ContentSize определяет только область окна scrollview. contentInset определяет прокручиваемую область.

Надеюсь, это поможет кому-то в такой же ситуации.

Роберт Васманн
источник
Для UITextView используйте keyPath "textContainerInset"
Дима Деплов
4

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

Это означает, что вы можете, например, закрепить свой scrollview в нижней части основного представления с нулевым полем, а также закрепить содержимое вашего scrollview в нижней части scrollview с нулевым полем, но содержимое фактически не будет растягиваться при этом. Вместо этого контент получит свой размер, определяемый самостоятельно (подробнее см. Ниже), и это также будет размер прокручиваемой области в области просмотра.

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

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

Я наткнулся на это случайно, а затем, увидев, как это работает, привел меня к этой статье, которая полностью объясняет это и цитирует источник документации Apple для этого:

https://spin.atomicobject.com/2014/03/05/uiscrollview-autolayout-ios/

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

Пэт Нимейер
источник
2

Если вы щелкните значок «Свойства» любого контроллера представления в Interface Builder, вы можете установить для него размер «произвольной формы» в смоделированных показателях и изменить размер основного представления на желаемый размер содержимого.

Таким образом, вы можете создавать содержимое ScrollView, как если бы это было одно большое представление. Поскольку это всего лишь смоделированная метрика, размер вашего контроллера представления будет изменен до границ окна при загрузке.

Олиланд
источник
2

Настройка UIScrollView через Interface Builder не является интуитивно понятной. Вот мой контрольный список для его настройки:

  1. Выберите файл XIB UIViewController. В «Инспекторе идентичности» конструктора интерфейсов измените UIView на тип класса UIScrollView

  2. В разделе "Инспектор файлов" снимите флажок "Автоформат

  3. В «Инспекторе атрибутов» измените размер на Freeform. Затем вы можете растянуть прокрутку вручную или указать произвольную ширину и высоту в «Инспекторе размеров».

  4. В «Инспекторе идентичности» добавьте новый определяемый пользователем атрибут времени выполнения с именем «contentSize» типа «Размер» и измените его на значение, подобное {320, 1000}. Вы больше не можете установить это программно и, следовательно, вам нужен этот шаг, чтобы Scroll View знал, что содержимое Scroll View больше, чем окно.

Свободный масон
источник
2

Просто удалите autoLayout из вашего scrollview. тогда код будет таким простым:

scrollviewName.contentSize = CGSizeMake(0, 650);

просто создайте свойство iboulet в файле .h, а затем синтезируйте его в файле .m. Убедитесь, что прокрутка включена.

Олдрин Эквила
источник
1

Да, st3fan прав, свойство contentSize UIScrollView должно быть установлено. Но отключать автопрокладку для этого не стоит. Вы легко можете настроить contentSize для UIScrollView с автоматическим размещением только в IB, без какого-либо кода.

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

Например, если у вас есть только одно подпредставление, вы можете установить его высоту и пространство сверху и снизу до супервизора (т.е. scrollView в нашем случае) contentSize.height рассчитывается как сумма

Vertical Space (aSubview.top to Superview.top) + aSubview.height + Vertical Space (aSubview.top to Superview.top)

contentSize.width рассчитывается аналогично из горизонтальных ограничений.

Если слишком мало ограничений для правильного расчета contentSize, рядом с элементом View Controller Scene отображается маленькая красная кнопка, чтобы сообщить о неоднозначности макета.

Если есть много подвидов , то это может быть «цепь» ограничения: сверху верхний подвид, высоту и пространство между подвидами и нижним подвидом вниз , как в Danyal Айтекин ответа.

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

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

Владимир
источник
1

У вас может быть UIScrollView в StoryBoard с Autolayouts. В основном вам нужно:

  1. Добавить UIScrollView
  2. Добавьте к нему все ограничения (например, вставки сверху, слева, справа, снизу)
  3. Добавить "контейнер" UIView в UIScrollView
  4. Если вам нужна только однонаправленная прокрутка (например, вертикальная): явно задайте высоту (например, 600) и ширину ссылки равной ширине UIScrollView.
  5. Если вам нужна двунаправленная прокрутка, просто установите ширину и высоту.

настройка раскадровки

Евгений Брагинец
источник
0

Вот решение для разработки ScrollView с содержимым, превышающим размер экрана, полностью в Storyboard (ну, почти полностью, вам также нужно добавить одну строку кода)

https://stackoverflow.com/a/19476991/1869369

Ронни Веберс
источник
0

Нахожу более удобный способ.

1: масштабировать размер прокрутки так, чтобы внутри нее находился весь пользовательский интерфейс.

2: Добавить iboutlet для просмотра прокрутки.

3: В viewDidLoad сохраните размер кадра прокрутки.
(например, _scrollSize = _scrollView.frame.size;)

4: В viewWillAppear установите contentSize на CGSize, который вы сохранили ранее.
(например, _scrollView.contentSize = _scrollSize;)

5: Готово ~

Agas
источник
0
  1. Добавить UIViewController
  2. В UIViewController 'Attribute Inspector -> Simulated Metrics' установите размер Freeform
  3. В UIViewController 'Size Inspector -> View Controller' установите высоту 800
  4. Добавить UIScrollView в UIViewController
  5. Добавьте все ограничения в UIScrollView (сверху, слева, справа, снизу) и добавьте выравнивание X = center
  6. Добавить UIView в UIScrollView
  7. Добавьте все ограничения в UIView (сверху, слева, справа, снизу) и добавьте выравнивание X = center. Да, так же, как для UIScrollView в №3, но для UIView
  8. Добавьте ограничение высоты в UIView. Например 780
  9. Бегать

Раскадровка

Александр
источник
0

Создать новый проект Xcode

Перейдите к файлу Main.storyboard

Выберите ScrollView из библиотеки объектов.

Установите рамку для ScrollView.

Добавьте другое представление для прокрутки и оставьте фрейм таким же, как у ScrollView.

Теперь, чтобы установить его высоту и ширину динамически, вы можете настроить UIScrollView с помощью автоматического макета в XIB.

Дилрадж Сингх
источник