Переворачиваем вечный SwiftUI календарь при помощи UIKit

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.
Данная статья написана в развлекательных целях. Если вам интересно следить за самыми последними новостями 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]
    }
}

Источник: https://habr.com/ru/companies/broadcast/articles/758470/


Интересные статьи

Интересные статьи

WWDC 2022 привнесла много изменений и улучшений в SwiftUI, и обновленный протокол Layout — одно из самых значимых. Об особенностях работы с новыми инструментами компоновки элементов, анонсированными в...
Quarkus поставляется с набором инструментов, позволяющих разработчикам быстро начать разработку используя расширения для многих популярных IDE. Одной из наиболее известных и простых в использовании фу...
Слышали про такой инструмент, как Airtable, но не знали, с чего начать? Тогда приглашаем в мир визуального программирования построения БД! Этим постом мы начинаем цикл обучающих статей, ...
На текущей работе пишем на Reactor. Технология классная, но как всегда есть много НО. Некоторые вещи раздражают, код сложнее писать и читать, с ThreadLocal совсем беда. Р...
Наверняка многие из вас бывали в ситуации, когда нужно быстро подобрать цвета для оформления, а дизайнер занят более важными задачами, в плохом настроении или в отпуске. Задача несл...