Slide-Out Navigation Panel in Swift for IOS Applications

The slide-out navigation panel design pattern lets developers add stable navigation to their apps without taking up beneficial screen real estate. The user can choose to acknowledge the navigation at any time, while still looking their present context.


Getting Started
You’re going to create a slide-out navigation panel into a beautiful kitten and puppy photo browser. To get started, download the starter project. It’s a zip file, so save it to an acceptable location and then extract it to get the project.

Next open the project in Xcode and take a see at how it’s organized. The Assets folder contains a couple of asset catalogs of the whole kitten and puppy pictures that’ll be showed in the app. Notice too there’s three main view controllers. Here’s what you should keep in mind:

ContainerViewController: This is where the magic happens! This contains the views of the left, center, and right view controllers and handles things like animations and swiping. In this project, it’s madeand added to the window in application(_:didFinishLaunchingWithOptions:) in AppDelegate.swift

CenterViewController: The center panel. You can change it with your own view controller (make assured you copy the button actions).

SidePanelViewController: Utilized for the left and right side panels. This could be changed with your own view controller.

The views for the center, left and right view controllers are all defined within Main.storyboard, so feel free to take a rapid look to get an idea of how the app will look.

Now you’re usual with the structure of the project, it’s time to begin at square one: the center panel.

Finding Your Center

In this phase, you’re going to place the CenterViewController inside the ContainerViewController, as a child view controller.

Open ContainerViewController.swift. At the bottom of the file there’s a little extension for UIStoryboard. It adds a few static techniques which make it a bit more succinct to load particular view controllers from the app’s storyboard. You’ll make use of these techniques soon.

Add a couple of properties to ContainerViewController for the CenterViewController and for a UINavigationController, above viewDidLoad():

var centerNavigationController: UINavigationController!

var centerViewController: CenterViewController!

Next, add the following block of code to viewDidLoad(), beneath the call to super:

centerViewController = UIStoryboard.centerViewController()

centerViewController.delegate = self


// wrap the centerViewController in a navigation controller, so we can push views to it

// and display bar button items in the navigation bar

centerNavigationController = UINavigationController(rootViewController: centerViewController)

view.addSubview(centerNavigationController.view)

addChildViewController(centerNavigationController)

centerNavigationController.didMove(toParentViewController: self)

The code above builds a new CenterViewController and assigns it to the centerViewController property you just made. It also makes a UINavigationController to contain the center view controller. It then adds the navigation controller’s view to ContainerViewController‘s view and sets up the parent-child relationship utilizing addSubview(_:), addChildViewContoller(_:) and didMove(toParentViewController:).

It also sets the present view controller as the center view controller’s delegate. This will be utilized by the center view controller to tell its container when to display and hide the left and right side panels.

If you try to create now, you’ll look an error when the code assigns the delegate. You need to modify this class so it implements the CenterViewControllerDelegate protocol. You’ll add an extension to ContainerViewController to implement it. Add the following code above the UIStoryboard extension near the bottom of the file (this also includes a number of empty techniques which you’ll fill out later):

// MARK: CenterViewController delegate

extension ContainerViewController: CenterViewControllerDelegate {

  func toggleLeftPanel() {
  }

  func toggleRightPanel() {
  }

  func addLeftPanelViewController() {
  }

  func addRightPanelViewController() {
  }

  func animateLeftPanel(shouldExpand: Bool) {
  }

  func animateRightPanel(shouldExpand: Bool) {
  }
}

Now is a best time to check your progress. Create and run the project.

Kittens to the Left of Me
You’ve created your center panel, but adding the left view controller requires a various set of stages. There’s quite a bit of set up to get through here, so bear with it. Think of the kittens!

To expand the left menu, the user will tap on the Kitties button in the navigation bar. So head on over to CenterViewController.swift.

In the interests of keeping this on the important stuff, the IBActions and IBOutlets are pre-connected for you in the storyboard. However, to implement your DIY slide-out navigation panel, you require understanding how the buttons are configured.

Notice there’s already two IBAction techniques, one for each of the buttons. Find kittiesTapped(_:) and add the following implementation to it:
delegate?.toggleLeftPanel?()

This uses optional chaining to only call toggleLeftPanel() if delegate has a value and it has implemented the technique.

You can look the definition of the delegate protocol in CenterViewControllerDelegate.swift. As you’ll see, there’s optional techniques toggleLeftPanel() and toggleRightPanel(). If you remember, when you set up the center view controller examples earlier, you set its delegate as the container view controller. Time to go and implement toggleLeftPanel().

Open ContainerViewController.swift. First add an enum to the ContainerViewController class, right below the class name:

class ContainerViewController: UIViewController {

  enum SlideOutState {
    case bothCollapsed
    case leftPanelExpanded
    case rightPanelExpanded
  }

// ...

This will let you keep track of the present state of the side panels, so you can tell whether neither panel is visible, nor one of the left or right panels is visible.

Next, add two more properties below your existing centerViewController property:

var currentState: SlideOutState = .bothCollapsed

var leftViewController: SidePanelViewController?
These will hold the present state, and the left side panel view controller itself:

The present state is initialized to be .bothCollapsed – that is, neither of the side panels are visible when the app first loads. The leftViewController property is an optional, because you’ll be adding and deleting the view controller at different times, so it might not ever have a value.

Next, add the implementation for the toggleLeftPanel() delegate technique:

let notAlreadyExpanded = (currentState != .leftPanelExpanded)

if notAlreadyExpanded {
  addLeftPanelViewController()
}

animateLeftPanel(shouldExpand: notAlreadyExpanded)

First, this techniques checks whether the left side panel is already developed or not. If it’s not already visible, then it adds the panel to the view hierarchy and animates it to its ‘open’ position. If the panel is already visible, then it animates the panel to its ‘closed’ position.

And sliiiiiiide!

First, add a constant below your other properties in ContainerViewController.swift:

let centerPanelExpandedOffset: CGFloat = 60

This value is the width, in points, of the center view controller left visible once it has animated off screen. 60 points should do it.

Next, locate the technique stub for animateLeftPanel(shouldExpand:) and add the following block of code to it:

if shouldExpand {
  currentState = .leftPanelExpanded
  animateCenterPanelXPosition(
    targetPosition: centerNavigationController.view.frame.width - centerPanelExpandedOffset)

} else {
  animateCenterPanelXPosition(targetPosition: 0) { finished in
    self.currentState = .bothCollapsed
    self.leftViewController?.view.removeFromSuperview()
    self.leftViewController = nil
  }
}

This technique easily checks whether it’s been told to expand or collapse the side panel. If it should expand, then it sets the present state to indicate the left panel is expanded, and then animates the center panel so it’s open. Otherwise, it animates the center panel closed and then deletes its view and sets the present state to indicate it’s closed.

Finally,add animateCenterPanelXPosition(targetPosition:completion:) underneath animatedLeftPanel(shouldExpand:):
func animateCenterPanelXPosition(targetPosition: CGFloat, completion: ((Bool) -> Void)? = nil) {

  UIView.animate(withDuration: 0.5,
                 delay: 0,
                 usingSpringWithDamping: 0.8,
                 initialSpringVelocity: 0,
                 options: .curveEaseInOut, animations: {
      self.centerNavigationController.view.frame.origin.x = targetPosition
    }, completion: completion)
  }

This is where the certain animation happens. The center view controller’s view is animated to the specified position, with a nice spring animation. The technique also takes an optional conclusion closure, which it passes on to the UIView animation. You can try twisting the duration and spring damping parameters if you want to change the presence of the animation.

If you have any queries, write to us at info@vamediabox.com or if you are looking for IOS Applicaton Services, call at +91-9599449323

Comments

Popular Posts