ProudHKer
ProudHKer

Reputation: 85

How to set the PageViewController to cover the whole screen and not be modal?

I am implementing a UIPageViewController to my app to try to build a UI like Tinder, in which you can swipe left and right to not only like or dislike a person, but to navigate different screens, i.e. chat screen, profile screen, matches screen etc.

In my case, after signing in, a UIPageViewController that contains 4 other UIViewControllers will pop up.

However, the UIPageViewController is modal and doesn't cover the whole screen(as there is a small gap at the top which allows the user to swipe the modal down and away). enter image description here I tried using code like this:

self.window = UIWindow(frame: UIScreen.main.bounds)
    if let window = self.window {
        window.rootViewController = PageViewController()
        window.makeKeyAndVisible()
    }

at my AppDelegate, or setting Full Screen at the storyboard, but did't work.

I wonder how I should do this? Or maybe UIPageViewController is not the right choice to achieve this swipe from screen to screen navigation style Tinder has?

Anyway, here is the code of my PageViewController:

import UIKit

class PageViewController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
   
    var controllers = [UIViewController]()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        let vc = TodayPicksViewController()
        controllers.append(vc)
        
        let vc1 = TopPicksViewController()
        vc1.view.backgroundColor = .yellow
        controllers.append(vc1)
        
        let vc2 = ChatViewController()
        vc2.view.backgroundColor = .gray
        controllers.append(vc2)
        
        let vc3 = (storyboard?.instantiateViewController(withIdentifier: String(describing: ProfileViewController.self)) as? ProfileViewController)!
        controllers.append(vc3)
        
    }
        
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        DispatchQueue.main.asyncAfter(deadline: .now()+2, execute: {
            self.presentPageVC()
        })
    }
    
    func presentPageVC() {
        guard let first = controllers.first else {
            return
        }
        
        let vc = UIPageViewController(transitionStyle: .scroll,
                                      navigationOrientation: .horizontal,
                                      options: nil)
        
        vc.delegate = self
        vc.dataSource = self
        vc.setViewControllers([first],
                              direction: .forward,
                              animated: true,
                              completion: nil)
        present(vc, animated: true)
    }
    
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        guard let index = controllers.firstIndex(of: viewController), index > 0 else {
            return nil
        }
        
        let before = index - 1
        
        return controllers[before]
    }
    
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        guard let index = controllers.firstIndex(of: viewController), index < (controllers.count - 1) else {
            return nil
        }
        
        let after = index + 1
        
        return controllers[after]
    }
}

Upvotes: 0

Views: 979

Answers (1)

Andrew
Andrew

Reputation: 28539

By default when you present a ViewController in Swift it doesn't cover the fullscreen. To make it cover the fullscreen you need to set the modalPresentationStyle on the ViewController.

So in your presentPageVC method you need to add the following line :

vc.modalPresentationStyle = .fullScreen

So your method will now look like this:

func presentPageVC() {
    guard let first = controllers.first else {
        return
    }
    
    let vc = UIPageViewController(transitionStyle: .scroll,
                                    navigationOrientation: .horizontal,
                                    options: nil)
    
    vc.delegate = self
    vc.dataSource = self
    vc.setViewControllers([first],
                            direction: .forward,
                            animated: true,
                            completion: nil)

    vc.modalPresentationStyle = .fullScreen // <- add this before presenting your ViewController

    present(vc, animated: true)
}

To read more about the different presentation styles that you can have check out the documentation here.

Upvotes: 2

Related Questions