Данная статья написана в развлекательных целях. Если вам интересно следить за самыми последними новостями iOS разработки и получать подборку интересных статей по этой тематике, тогда вам стоит подписаться на Телеграм-канал iOS Broadcast
Предположим, вам прилетела срочная задача: реализовать календарь, который ведет себя как физический перекидной календарь в котором на каждой странице 3 сентября.
Для начала сверстаем страницу календаря:
struct CalendarView: View {
var body: some View {
ZStack {
VStack {
ZStack {
Text("Сентябрь")
.foregroundColor(.red)
.font(.system(.body))
}
Text("3")
.font(.largeTitle)
}
}
.overlay(
RoundedRectangle(cornerRadius: 20)
.stroke(.black, lineWidth: 0.5)
.frame(width: 100, height: 100)
)
}
}
Теперь добавим переворот страницы используя старый добрый UIPageViewController
lazy var pageViewController = UIPageViewController(
transitionStyle: .pageCurl,
navigationOrientation: .vertical
)
override func viewDidLoad() {
super.viewDidLoad()
pageViewController.dataSource = self
addChild(pageViewController)
view.addSubview(pageViewController.view)
pageViewController.setViewControllers([UIHostingController(rootView: CalendarView())], direction: .forward, animated: false)
}
Для того чтобы сделать бесконечный календарь достаточно 2 инстансов CalendarView:
lazy var views: [UIViewController] = [
UIHostingController(rootView: CalendarView()),
UIHostingController(rootView: CalendarView()),
]
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
guard let index = views.firstIndex(of: viewController) else {
return nil
}
return page(at: index - 1)
}
func pageViewController(_ pageViewController: UIPageViewController,
viewControllerAfter viewController: UIViewController) -> UIViewController? {
guard let index = views.firstIndex(of: viewController) else {
return nil
}
return page(at: index + 1)
}
func page(at index: Int) -> UIViewController? {
guard index > 0 else {
return views.last
}
guard index < views.count else {
return views.first
}
return views[index]
}
Таким образом мы получаем зацикленный календарь который можно вечно переворачивать и видеть снова 3 сентября.
Полный листинг кода
import UIKit
import SwiftUI
struct CalendarView: View {
var body: some View {
ZStack {
VStack {
ZStack {
Text("Сентябрь")
.foregroundColor(.red)
.bold()
.font(.system(.body))
}
Text("3")
.font(.largeTitle)
}
}
.overlay(
RoundedRectangle(cornerRadius: 20)
.stroke(.black, lineWidth: 0.5)
.frame(width: 100, height: 100)
)
}
}
class ViewController: UIViewController, UIPageViewControllerDataSource {
lazy var pageViewController = UIPageViewController(
transitionStyle: .pageCurl,
navigationOrientation: .vertical
)
lazy var views: [UIViewController] = [
UIHostingController(rootView: CalendarView()),
UIHostingController(rootView: CalendarView()),
]
override func viewDidLoad() {
super.viewDidLoad()
pageViewController.dataSource = self
addChild(pageViewController)
view.addSubview(pageViewController.view)
pageViewController.setViewControllers([views.first!], direction: .forward, animated: false)
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController?
{
guard let index = views.firstIndex(of: viewController) else {
return nil
}
return page(at: index - 1)
}
func pageViewController(_ pageViewController: UIPageViewController,
viewControllerAfter viewController: UIViewController) -> UIViewController?
{
guard let index = views.firstIndex(of: viewController) else {
return nil
}
return page(at: index + 1)
}
func page(at index: Int) -> UIViewController? {
guard index > 0 else {
return views.last
}
guard index < views.count else {
return views.first
}
return views[index]
}
}