Update: Check out this updated blog post which uses a better approach to creating slideout menus.
This is a sample project with a left slideout menu, and a two-tabbed application for the main body. The majority of the setup is done in the Storyboard.
This repo is tied to this blog post.
Apps tend to have a top level container like a Tab Bar Controller
that cannot be embedded inside a View. The approach here is to wrap the main body and the left menu each inside a Container View
. Now both of these elements can be arranged inside a wrapper View Controller
.
A ScrollView
is used to simulate opening and closing the menu by shifting the left menu on/off-screen.
Since Storyboard changes aren't really portable across projects, here is a recipe on how to recreate this.
Start with a Tabbed Application
. This is just to demonstrate that even a Tab Bar Controller
can be used with slideout menus.
Uncheck the box Use Size Classes
for now, simply for the sake of screen real estate.
Drop a View Controller
onto the Storyboard. This is your entry point into the app, and acts as a big wrapper. Think of a Laundry Sorting Cart that can hold baskets for lights and darks. Or in this case, a Menu and Tab Bar Controller.
Check the box for Is Initial View Controller
.
Change the Simulated Size
from Fixed
to Freeform
. Set the Width
to 568 so we can fit the menu and Tab Bar side-by-side.
Create a new Swift file and set this View Controller's class to ContainerVC.
import UIKit
class ContainerVC : UIViewController {
}
Inside Container View Controller, drop in a ScrollView
and add constraints in all directions.
Check the box for Scrolling Enabled
. This allows you to pan the screen to slide the menu. You might need to disable this if your app uses horizontally scrolling elements.
Check the box for Paging Enabled
. This snaps the menu to either the open or closed state.
Uncheck the box for Bounces
. You don't really want to scroll past the right edge of the Tab Bar Controller.
Wire the IBOutlet to ContainerVC:
@IBOutlet weak var scrollView: UIScrollView!
The left container holds the menu, and is not quite the full width of the screen.
Drag a Container View
into the left side of the ScrollView
.
Add constraints for top, left, and right to the containing ScrollView
.
Hard-code the width to 260.
Add a constraint for Equal height
with the ContainerVC's embedded View
. Note: don't constrain the height to the ScrollView.
Delete the embedded View Controller
that came with the Container View
.
Drop a new Table View Controller
onto the Storyboard, and connect using an embed
segue.
The right container holds the main body of your app, namely the Tab Bar Controller
.
Drag a second Container View
into the right side of the ScrollView
.
Add constraints to the containing ScrollView
for top, right, and bottom. Connect horizontally to the left Container View
you created earlier.
Constraint both Equal height
and Equal width
to the ContainerVC's embedded View
. Note: do not constrain these to the ScrollView.
Here's a short demo of setting the Equal height
and width
constraints to the View
:
Again, delete the embedded View Controller that came free with the Container View
. Instead, create an embed
segue to the Tab Bar Controller
.
To create a little visual separation between the two containers, add a Runtime Attribute
to the Right Container
. Add layer.shadowOpacity
with a number
of 0.8
.
Embed each tab inside a Navigation Controller
. Doing so gives you a free Navigation Bar
.
Drag a Bar Button Item
into the top left corner of each Navigation Bar
.
Wire an IBAction
to each controller. These will fire off a NSNotification
to the great-grandfather ContainerVC
to toggle the menu.
@IBAction func toggleMenu(sender: AnyObject) {
NSNotificationCenter.defaultCenter().postNotificationName("toggleMenu", object: nil)
}
Most of the Storyboard configuration is done. All that's left is to copy the code from ContainerVC.swift.
The code accomplishes the following:
Build and run, and hopefully you have a simple slideout left menu on which to build the rest of your app.
The ScrollView
is pretty confusing to begin with. One common trick is to have a rigidly defined view on the inside. In this case, the left and right container views are constrained to the device (View Controller's embedded View
) width and height. The ScrollView
acts like a flexible wrapper.
Here's an excellent video tutorial on Ray Wenderlich that covers the ScrollView
. Note parts 13 and 14 cover the Slide-out-sidebar upon which the idea of using the ScrollView for a slideout menu is based upon.