Как стать автором
Обновить
0
Broadcasts Group
Образовательный проект о мобильной разработке

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

Уровень сложностиПростой
Время на прочтение3 мин
Количество просмотров2.3K
Данная статья написана в развлекательных целях. Если вам интересно следить за самыми последними новостями 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]
    }
}

Теги:
Хабы:
Всего голосов 20: ↑10 и ↓10+7
Комментарии3

Публикации

Информация

Сайт
androidbroadcast.dev
Дата регистрации
Дата основания
Численность
1 человек (только я)
Местоположение
Беларусь

Истории