1

I would push a UINavigationController in the same way Favorite/Bookmarks Folders are presented in iOS Safari:

Safari Push Animation

I already tried using a single UINavigationController, setting navigationController?.setNavigationBarHidden(true, animated: false) in viewWillAppear for the first view, but I can't get the desidered behavior: I would have the navigationbar to slide in when child viewControllers are pushed and to slide out when returning to the rootViewController.

Any suggestion? I'm using Swift 4.0.3, developing target iOS 11, thanks in advance.

Edit

I tried to achieve the wanted behavior by nesting two UINavigationControllers:

mainNavController: UINavigationController           // with hidden NavigationBar
  - firstFavoritePage: UIViewController             // as rootViewController
  - wrapper: UIViewController                       // a containerViewController
    - nestedNavController: UINavigationController
      - blankPageWithTitleAll: UIViewController     // as rootViewController
      - folderPage: UIViewController

I added a wrapper container ViewController since two UINavigationControllers are merged while directly nested (to have UISplitViewController working as expected) and I added a blank page in the inner NavigationController with the title "All" to get the "< All" back button to animate correctly on pushes (a custom back button fades out, a real back button not).

In Swift:

let wrapper = UIViewController()
let blankPageWithTitleAll = UIViewController()
let folderPage = UIViewController()
let nestedNavController = UINavigationController(rootViewController: blankPageWithTitleAll
wrapper.addChildViewController(nestedNavController)
wrapper.view.addSubview(nestedNavController.view)
nestedNavController.view.anchorToSuperview(wrapper.view)
nestedNavController.didMove(toParentViewController: wrapper)
nestedNavController.pushViewController(folderPage, animated: false)
blankPageWithTitleAll.navigationItem.title = "All"
firstFavoritePage.show(wrapper, sender: self)

Now the presenting animation works as expected, but to dismiss everything, if the active ViewController is the second or first controller of the nestedNavController navigation stack, I should:

  • prevent the nestedNavController interactive pop transition;
  • prevent the nestedNavController back button pop transition;
  • add a custom action when the "< All" back button is pressed to pop the mainNavController instead of the nestedNavController;
  • [probably the most difficult thing to do] mirror the pop UIPercentDrivenInteractiveTransition (the edge swipe to go back interactive animation) of the nestedNavController to the mainNavController.

I don't even know if I can get or set percentage values for that animated transition (I don't think it could be possible.. but I'll try to figure out if it is).

Any other way (possibly simpler) to have this working correctly is highly appreciated, thanks.

xAlien95
  • 346
  • 4
  • 16
  • if you want to have the navigation controller show up in the second view, instead of embedding the first view with navigation controller and trying to hide it until the second view, why don't you just have your view hierarchy be 'first view -> navigation controller -> second view' ? – dinosaysrawr Jan 31 '18 at 23:08
  • @dinosaysrawr because presenting a UINavigationController from a UIViewController will have the classic modal transition sliding from bottom and you won't get the "< All" back button, neither the `UIViewControllerInteractiveTransitioning` that UINavigationControllers have for the edge pop gesture. If you take the path you suggested, I should code myself a clone of the `UIViewControllerTransitioningDelegate` UINavigationController uses, implementing `UIViewControllerAnimatedTransitioning` and `UIPercentDrivenInteractiveTransition` both. – xAlien95 Jan 31 '18 at 23:19
  • I just had an idea though: navigation controller with hidden navigation bar and another navigation controller as child viewcontroller. I'm not completely sure if the pop interactive gesture will work as expected. – xAlien95 Jan 31 '18 at 23:22

1 Answers1

2

You can archive this type of behaviour using embedded view controller. See my view hierarchy in image : enter image description here You can embedded navigation controller as subview.

In Last view you have to create view like navigation bar, and you have to write code for pop view controller.

Here is the code :

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

class MainViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

class SubViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        self.navigationController?.interactivePopGestureRecognizer?.delegate = nil
    }
    @IBAction func onClickBack(_ sender: UIButton) {
        self.navigationController?.popViewController(animated: true)

    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

Actual Result :

Jayesh Thanki
  • 2,037
  • 2
  • 23
  • 32
  • I thought the same: nesting two UINavigationControllers (I updated the question). As you can see here (https://i.imgur.com/G3O5CPP.gif) your solution doesn't completely solve the problem, since you're adding a constructed navigation bar, while the sub navigation controller needs to have a real one (with all the transition animations working correctly). But, despite this, you're answer is quite useful: `self.navigationController?.interactivePopGestureRecognizer?.delegate = nil`, I didn't know that it's possible to get or set the popGestureRecognizer of a navigation controller. – xAlien95 Feb 01 '18 at 10:53
  • Ref : https://stackoverflow.com/questions/24710258/no-swipe-back-when-hiding-navigation-bar-in-uinavigationcontroller/31386455. Without navigation bar `interactivePopGestureRecognizer` not working thats why i have set it nil delegate . – Jayesh Thanki Feb 01 '18 at 12:13
  • Here is my code : https://www.dropbox.com/s/f0bghn264c2d8li/NavigationDemo.zip?dl=0. I have fixed navigation issues please check and let me know. – Jayesh Thanki Feb 01 '18 at 12:37
  • i have remove custom view for navigation and attached real navigation. so you can now enjoy original push pop transitions. – Jayesh Thanki Feb 01 '18 at 12:38