以编程方式创建部分屏幕的UIPageViewController [英] Create partial-screen UIPageViewController programmatically

查看:59
本文介绍了以编程方式创建部分屏幕的UIPageViewController的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建仅占据屏幕一部分的滚动pageviewcontroller.我已经成功使用Storyboard和ContainerView对象完成了此操作,但是现在我需要以编程方式复制创建项目的功能.

I am trying to create a scrolling pageviewcontroller that only takes up part of my screen. I have successfully done this using Storyboard and a ContainerView object, but I now need to replicate the functionality creating the project programmatically.

似乎我不能使用swift创建ContainerView,因此我尝试使用UIView充当容器,并尝试使用UIPageViewController进行addSubview,但出现错误cannot convert value of type UIPageViewController to expected argument type UIView.

It seems that ContainerView is not something that I can create using swift, so I tried to do this using a UIView to act as a container that I tried to do addSubview with a UIPageViewController, but I get the error cannot convert value of type UIPageViewController to expected argument type UIView.

我假设我在这里肯定会缺少一些简单的东西,因为正如我说的那样,我已经使用Storyboard/Interface Builder完成了此工作,但是在使用Swift进行编程构建时,如何获得类似的功能呢?

I assume that I must be missing something simple here, since as I said, I've accomplished this with Storyboard/Interface Builder, but how can I get similar functionality while building programmatically with Swift?

推荐答案

UIContainerView确实只是一个Storyboard的便利.它添加了一个普通的UIView,并允许您将View Controller作为其嵌入内容"进行连接.

UIContainerView is really just a Storyboard convenience. It adds a normal UIView and allows you to connect a View Controller as its "embedded content."

但是,在幕后,它确实在执行您可以通过代码执行的操作:

But, under the hood, it is doing exactly what you can do from code:

  • 在主视图中添加UIView,将其用作容器"
  • 实例化您的页面视图控制器
  • 使用addChild(_ childController: UIViewController)将该页面视图控制器添加为子控制器
  • 将子级VC的视图添加到容器"视图
  • add a UIView to your main view that you will use as the "container"
  • instantiate your page view controller
  • use addChild(_ childController: UIViewController) to add that page view controller as a child controller
  • add the child VC's view to your "container" view

这是一个完整的示例:

//
//  Created by Don Mag on 5/31/19.
//

import UIKit

// simple example view controller
// has a label 90% of the width, centered X and Y
class ExampleViewController: UIViewController {

    let theLabel: UILabel = {
        let v = UILabel()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.backgroundColor = .white
        v.textAlignment = .center
        return v
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(theLabel)
        NSLayoutConstraint.activate([
            theLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            theLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            theLabel.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.9),
            ])

    }

}

// example Page View Controller
class MyPageViewController: UIPageViewController {

    let colors: [UIColor] = [
        .red,
        .green,
        .blue,
        .cyan,
        .yellow,
        .orange
    ]

    var pages: [UIViewController] = [UIViewController]()

    override init(transitionStyle style: UIPageViewController.TransitionStyle, navigationOrientation: UIPageViewController.NavigationOrientation, options: [UIPageViewController.OptionsKey : Any]? = nil) {
        super.init(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        dataSource = self
        delegate = nil

        // instantiate "pages"
        for i in 0..<colors.count {
            let vc = ExampleViewController()
            vc.theLabel.text = "Page: \(i)"
            vc.view.backgroundColor = colors[i]
            pages.append(vc)
        }

        setViewControllers([pages[0]], direction: .forward, animated: false, completion: nil)
    }

}

// typical Page View Controller Data Source
extension MyPageViewController: UIPageViewControllerDataSource {
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {

        guard let viewControllerIndex = pages.index(of: viewController) else { return nil }

        let previousIndex = viewControllerIndex - 1

        guard previousIndex >= 0 else { return pages.last }

        guard pages.count > previousIndex else { return nil }

        return pages[previousIndex]
    }

    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        guard let viewControllerIndex = pages.index(of: viewController) else { return nil }

        let nextIndex = viewControllerIndex + 1

        guard nextIndex < pages.count else { return pages.first }

        guard pages.count > nextIndex else { return nil }

        return pages[nextIndex]
    }
}

// typical Page View Controller Delegate
extension MyPageViewController: UIPageViewControllerDelegate {

    // if you do NOT want the built-in PageControl (the "dots"), comment-out these funcs

    func presentationCount(for pageViewController: UIPageViewController) -> Int {
        return pages.count
    }

    func presentationIndex(for pageViewController: UIPageViewController) -> Int {

        guard let firstVC = pageViewController.viewControllers?.first else {
            return 0
        }
        guard let firstVCIndex = pages.index(of: firstVC) else {
            return 0
        }

        return firstVCIndex
    }
}

class MyTestViewController: UIViewController {

    let myContainerView: UIView = {
        let v = UIView()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.backgroundColor = .gray
        return v
    }()

    var thePageVC: MyPageViewController!

    override func viewDidLoad() {
        super.viewDidLoad()

        // add myContainerView
        view.addSubview(myContainerView)

        // constrain it - here I am setting it to
        //  40-pts top, leading and trailing
        //  and 200-pts height
        NSLayoutConstraint.activate([
            myContainerView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 40.0),
            myContainerView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 40.0),
            myContainerView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -40.0),
            myContainerView.heightAnchor.constraint(equalToConstant: 200.0),
            ])

        // instantiate MyPageViewController and add it as a Child View Controller
        thePageVC = MyPageViewController()
        addChild(thePageVC)

        // we need to re-size the page view controller's view to fit our container view
        thePageVC.view.translatesAutoresizingMaskIntoConstraints = false

        // add the page VC's view to our container view
        myContainerView.addSubview(thePageVC.view)

        // constrain it to all 4 sides
        NSLayoutConstraint.activate([
            thePageVC.view.topAnchor.constraint(equalTo: myContainerView.topAnchor, constant: 0.0),
            thePageVC.view.bottomAnchor.constraint(equalTo: myContainerView.bottomAnchor, constant: 0.0),
            thePageVC.view.leadingAnchor.constraint(equalTo: myContainerView.leadingAnchor, constant: 0.0),
            thePageVC.view.trailingAnchor.constraint(equalTo: myContainerView.trailingAnchor, constant: 0.0),
            ])

        thePageVC.didMove(toParent: self)
    }

}

结果:

这篇关于以编程方式创建部分屏幕的UIPageViewController的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆