Blog

Back to Blog

Creating a Double Overlay

Posted on 26 Jun 2013 Written by Thomas Kelly

The new release of ShinobiEssentials 2.0 is packed full of goodies, one of which was some slight modifications to the SEssentialsSlidingOverlay. The changes were small, but allow us to create a Sliding Overlay which can open from the left or right, to display different views on each side. This becomes especially useful on smaller devices where screen space is limited, as Facebook’s iPhone app has done to great effect.

Double

This post will guide you through how to create it yourself. I use ARC to keep things simple, but you can easily do the same with your own memory management. You can download the source of the project or clone it from https://github.com/ShinobiControls/double-sliding-overlay, which may be useful when following the tutorial below. You’ll need a copy of the ShinobiEssentials Framework to use with this project. If you don’t have it already – download a trial version. As with all ShinobiEssentials components, you will also need to use the QuartzCore framework in your project.

To start with, create our two overlays, and add one as the subview of the other:

@implementation ViewController
{
    SEssentialsSlidingOverlay *leftOverlay;
    SEssentialsSlidingOverlay *rightOverlay;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
	// Do any additional setup after loading the view, typically from a nib.
    
    //Set up right
    rightOverlay = [[SEssentialsSlidingOverlay alloc] initWithFrame:self.view.frame andToolbar:NO];
    rightOverlay.underlayLocation = SEssentialsSlidingOverlayLocationRight;
    [self.view addSubview:rightOverlay];
    
    //Set up left
    leftOverlay = [[SEssentialsSlidingOverlay alloc] initWithFrame:self.view.frame];
    [rightOverlay addSubview:leftOverlay];
}
@end

We store the leftOverlay and rightOverlay inside separate variables, to get at them in a minute. We also turn off the toolbar on the outermost overlay. This is because we would otherwise have two toolbars displayed at the top, one for each Sliding Overlay.

Next, we want to stop both overlays being able to open at the same time. To do this, we make use of the Gesture Recognizer delegates, which receive messages when the state of the gesture changed. The gesture delegate provides a “shouldReceiveTouch” method, which allows us to block a gesture from acting on a touch by returning “NO”. Add ourselves as the delegate of the gesture recognizers for each Sliding Overlay.

In ViewController.h:

@interface ViewController : UIViewController<UIGestureRecognizerDelegate>
@end

And in viewDidLoad: in ViewController.m:

- (void)viewDidLoad
{
    ...

    rightOverlay.gestureRecognizer.delegate = self;
    leftOverlay.gestureRecognizer.delegate = self;
}

Simple enough, now to stop them both opening at the same time, we stop the closed Sliding Overlay from receiving touches when the other Sliding Overlay is open. This way, when we have one Sliding Overlay open, the only touch that either will respond to will be a drag to close the currently opened Sliding Overlay.

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gesture shouldReceiveTouch:(UITouch *)touch
{
    //Only open the underlay if the other underlay is hidden
    return [[self otherView:gesture] underlayHidden];
}

-(SEssentialsSlidingOverlay*)otherView:(UIGestureRecognizer*)gesture
{
    return (gesture.view == rightOverlay) ? leftOverlay : rightOverlay;
}

The final step is to make sure they both receive touches in the first place:

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gesture shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    return YES;
}

Simple enough!

The Toolbar

So now we have a Sliding Overlay which opens in both directions, however we still only have one button on the toolbar. To make it more obvious that it opens in both directions, we should give the user two buttons to press. To do this, we clone the existing button.

-(UIButton*)createCloneButton
{
    //Setup
    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    button.bounds = leftOverlay.toolbar.button.bounds;
    
    //Styling
    button.backgroundColor = leftOverlay.style.buttonTintColor;
    [button setImage:leftOverlay.style.buttonImage forState:UIControlStateNormal];
    [button setImage:leftOverlay.style.buttonPressedImage forState:UIControlStateHighlighted];
    
    //Masking
    UIImageView *maskView = [[UIImageView alloc] initWithImage:leftOverlay.style.buttonMask];
    maskView.frame = leftOverlay.toolbar.button.layer.bounds;
    button.layer.mask = maskView.layer;
    
    return button;
}

A lot of the properties we use to style the existing button (and the rest of the control) are on the SEssentialsSlidingOverlayStyle, so we can easily grab the properties out and create a custom button identical to the existing button. All that is left is to wire it up:

- (void)viewDidLoad
{
    ...
    
    UIButton *button = [self createCloneButton];
    button.center = CGPointMake(self.view.bounds.size.width - 40, 25);
    [button addTarget:rightOverlay action:@selector(toggleUnderlayAnimated:) forControlEvents:UIControlEventTouchUpInside];
    [leftOverlay.toolbar addSubview:button];
}

This way, whenever the button is pressed, it toggles the overlay to display or hide. If your app is going to be rotated, you may also need to set the autoresizingmask on the button.

Twobuttons

Perfect! We’ve created a Sliding Overlay which opens in two directions, displaying a different view on either side. If you haven’t already, you can download the source for the project or clone it from https://github.com/ShinobiControls/double-sliding-overlay to get you started on creating your own Double Sliding Overlay. The ShinobiEssentials team would love to hear what you end up building, so do let us know!

Back to Blog