UIPageViewController — это компонент пользовательского интерфейса iOS, который предлагает удобный способ навигации между последовательными страницами контента. Он использует постраничную модель представления, позволяющую пользователям пролистывать страницы влево или вправо с помощью жестов.
Особенно полезен в приложениях, где контент должен быть представлен в формате, напоминающем физические страницы. Например, в приложениях для чтения книг, образовательных курсах, галереях изображений или даже в некоторых типах интерактивных руководств. UIPageViewController обеспечивает дополнительный уровень привлекательности и удобства использования приложения.
Сегодня я хочу поделиться кратким и простым руководством о том, как просто и программно реализовать UIPageViewController. Итак, что же мы получим в итоге?
Для начала определим класс ContentViewController, который реализует собственный контроллер представления. Этот класс предназначен для использования в UIPageViewController, где каждая страница представлена экземпляром ContentViewController. Это позволяет легко создавать несколько страниц с различными цветами текста и фона:
class ContentViewController: UIViewController {
private lazy var textLabel: UILabel = {
let label = UILabel()
label.textAlignment = .center
label.textColor = .white
label.font = UIFont.systemFont(ofSize: 25, weight: .bold)
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
override func viewDidLoad() {
super.viewDidLoad()
setupViews()
setupConstraints()
}
private func setupViews() {
view.addSubview(textLabel)
}
private func setupConstraints() {
NSLayoutConstraint.activate([
textLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor),
textLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor),
textLabel.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.8)
])
}
func configure(with text: String, backgroundColor: UIColor) {
textLabel.text = text
view.backgroundColor = backgroundColor
}
}
configure(with:backgroundColor:):
Этот метод позволяет настроить textLabel
и цвет фона контроллера снаружи. Параметр text
используется для установки текста в textLabel
, а backgroundColor
- для установки цвета фона view
Теперь создадим класс PageViewController, который наследуется от UIPageViewController. Этот класс эффективно управляет созданием и отображением различных страниц, каждая из которых представлена экземпляром ContentViewController с настраиваемым цветом текста и фона:
class PageViewController: UIPageViewController {
var pages: [ContentViewController] = []
override func viewDidLoad() {
super.viewDidLoad()
self.dataSource = self
let pageData: [(String, UIColor)] = [
("Let's", .paleLavender),
("Get", .paleTurquoise),
("Started", .paleGreen)
]
for (text, color) in pageData {
let contentVC = ContentViewController()
contentVC.configure(with: text, backgroundColor: color)
pages.append(contentVC)
}
if let firstPage = pages.first {
setViewControllers([firstPage], direction: .forward, animated: true, completion: nil)
}
}
}
Что мы здесь делаем:
Создаем массив пустых страниц pages, который будет содержать экземпляры ContentViewController
Создаем массив кортежей pageData [(String, UIColor)], где каждый кортеж содержит строку и цвет. Эти данные используются для настройки каждой страницы в UIPageViewController
Проходим циклом по каждому элементу pageData (где каждый элемент - это кортеж) и для каждого элемента создаем новый экземпляр ContentViewController, далее вызывает метод configure для настройки contentVC и добавляем сконфигурированный contentVC в массив pages
Далее проверяем, находится ли первая страница в массиве страниц. Если страница существует, она устанавливается в качестве текущего активного контроллера в UIPageViewController
Устанавливает сам PageViewController в качестве источника данных (dataSource) для UIPageViewController. Это необходимо для управления содержимым страниц.
Все, что нам осталось сделать, это реализовать протокол UIPageViewControllerDataSource, который используется для предоставления контроллеров представления, которые будут отображаться в UIPageViewController:
extension PageViewController: UIPageViewControllerDataSource {
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
guard let contentVC = viewController as? ContentViewController,
let currentIndex = pages.firstIndex(of: contentVC),
currentIndex > 0 else {
return nil
}
return pages[currentIndex - 1]
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
guard let contentVC = viewController as? ContentViewController,
let currentIndex = pages.firstIndex(of: contentVC),
currentIndex < pages.count - 1 else {
return nil
}
return pages[currentIndex + 1]
}
}
Эти два метода обеспечивают логику отображения контроллера и плавную и последовательную навигацию между страницами.
Рассмотрим каждый метод подробно:
-
pageViewController(_:viewControllerBefore:):
Этот метод определяет, какой контроллер должен быть показан перед текущим контроллером в
UIPageViewController
guard let
проверяет, что текущий контроллер является экземпляромContentViewController
и определяет его текущий индекс в массивеpages
currentIndex > 0
гарантирует, что текущий контроллер не является первым в массиве, что позволяет избежать выхода за пределы массиваЕсли условие выполняется, метод возвращает контроллер представления, который находится перед текущим (
pages[currentIndex - 1]
). Если условие не выполняется, метод возвращаетnil
, указывая, что предыдущего контроллера нет
-
pageViewController(_:viewControllerAfter:):
Этот метод определяет, какой контроллер должен отображаться после текущего контроллера в
UIPageViewController
Аналогично первому методу,
guard let
проверяет, что текущий контроллер является экземпляромContentViewController
и определяет его индексcurrentIndex < pages.count - 1
проверяет, что текущий контроллер не является последним в массивеЕсли условие выполняется, метод возвращает следующий контроллер представления (
pages[currentIndex + 1]
). Если нет, то возвращаетnil
, указывая на отсутствие следующего контроллера
Добавляем в App или Scene:
let pageViewController = PageViewController(transitionStyle: .pageCurl, navigationOrientation: .horizontal, options: nil)
window?.rootViewController = pageViewController
PageViewController предлагает различные стили перехода и ориентации навигации:
Параметры TransitionStyle: параметр .pageCurl имитирует эффект перелистывания настоящей книги или журнала, .scroll предоставляет опцию, при которой страницы скользят горизонтально или вертикально.
NavigationOrientation определяет, будет ли пользователь перемещаться по страницам горизонтально или вертикально.
Mulish
Спасибо за статью, как раз то, что искал, чтобы без сторибодов!