Найти в Дзене
Разработка под iOS

UIScrollView

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

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

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

Итак, класс UIScrollView унаследован от UIView, поэтому его положением и размерами можно управлять через свойство frame, как в любом другом представлении. Конечно, для этого можно использовать и Auto Layout, о котором мы говорили в предыдущей статье, но UIScrollView может также управлять границами и внутреннего контента. Для этого есть свойства contentSize и contentOffset.

Рис. 1. Иллюстрация UIScrollView
Рис. 1. Иллюстрация UIScrollView

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

Рис. 2. ContentSize
Рис. 2. ContentSize

Второй параметр это contentOffset. Он изменяется, когда пользователь начинает перемещать контент внутри UIScrollView. Математически его можно определить следующим образом: это вектор от левого верхнего угла контента до угла самого UIScrollView. Программно же он определяется структурой CGPoint, где x будет изменяться, если перемещать контент по горизонтали, а y - по вертикали. Чем дальше пользователь перемещает контент, тем больше становятся эти значения. Конечно же, contentOffset можно изменять программно, чтобы пользователю показать то, что сейчас нужно.

Рис. 3. ContentOffset
Рис. 3. ContentOffset

Настройка UIScrollView

Настраивать UIScrollView можно двумя способами.

  • Вручную задавая contentSize, настраивая для этого frame контента.
  • С применением Auto Layout.

Рассмотрим первый вариант, который является более простым для понимания.

Итак, представим, что необходимо реализовать приветственный экран в приложении. На этом экране будут 3 картинки, которые нужно показать одну за одной, причем было бы хорошо акцентировать внимание на той картинке, на которой сейчас пользователь.

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

Следующей итерацией мы помещаем картинки в каталог Assets.

-4

Далее добавляем UIScrollView в корневое представление контролера. Также нам понадобится массив объектов UIImageView для настройки контента.

Теперь картинки созданы, но их размер еще не задан, также как и размер самого UIScrollView.

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

Чтобы правильно разместить 3 объекта UIImageView в UIScrollView, нужно определить размеры каждого из них, а также их положения внутри UIScrollView. С размерами все просто: они по ширине и высоте равны UIScrollView.

Рис. 4. Размеры компонентов UIImageView внутри UIScrollView
Рис. 4. Размеры компонентов UIImageView внутри UIScrollView

Осталось определиться с координатами.

Первая картинка находится в левом верхнем углу, поэтому для нее смещение по оси X и Y равно 0. Вторая же стоит от угла UIScrollView на значение ширины этого самого UIScrollView. Поэтому смещение по оси X равно ширине UIScrollView, тогда как по оси Y оно равно 0. С третьей картинкой все аналогично, только она стоит по оси X на две ширины UIScrollView.

Рис. 5. ContentOffset элементов UIImageView
Рис. 5. ContentOffset элементов UIImageView

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

Посмотрим, что получилось.

-7

Теперь рассмотрим второй вариант настройки UIScrollView. Настройку через Auto Layout.

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

Также важной особенностью является следующее: чтобы контент внутри UIScrollView можно было прокручивать, UIScrollView должен сам определить свой contentSize, используя Auto Layout.

Итак, вернемся к настройкам экрана приветствия и удалим ручное задание параметра contentSize.

В пустом UIScrollView размещаем 3 элемента UIImageView с нужными картинками. Для каждого из них создаем фиксированное расстояние для всех сторон до контейнера, а также расстояние между собой.

Рис. 6. Ограничения для компонентов UIImageView
Рис. 6. Ограничения для компонентов UIImageView

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

Рис. 7. Ограничения для компонентов UIImageView
Рис. 7. Ограничения для компонентов UIImageView

Реализуем это в коде.

И проверим получившийся результат.

-10

Проектирование интерфейса с помощью UIScrollView

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

Первым делом удалим файл ViewController.swift из проекта UIScrollViewProject и создадим новый файл под названием LoginViewController.swift

Далее отрисуем представление.

Взглянем, что получилось.

На экране видим заголовок экрана авторизации, его описание, а также два компонента типа UITextField и кнопку.

-11

Заметим, что на небольших экранах клавиатура перекрывает часть контента, в частности кнопку. С точки зрения дизайна это не user friendly.

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

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

-12

Клавиатура при этом убирается при нажатии на любую часть экрана.

-13

Бонус. Работа с UITextFieldDelegate

Стоит еще упомянуть про UITextFieldDelegate.

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

Итак, давайте реализуем данный функционал. Пусть LoginViewController, корневое вью которого и является супервью для UITextField, будет реализовывать UITextFieldDelegate. Причем при установке курсора в UITextField, будем подсвечивать его анимированным увеличением соответствующей сепаратора.

Финальный результат выглядит так.

-14
-15

На этом рассмотрение UIScrollView окончено. В следующей статье мы разберем и рассмотрим такой компонент как UITableView.