I first had the need for something like JDFPeekaboo while working on ER Browser. ER Browser is a web browser, so it greatly benefits from being able to move its navigation bars and toolbars out of the way, leaving the user with the whole screen to use for their web-browsing pleasure.

I originally implemented something similar, specifically for ER Browser. But, as it was something that would obviously be useful for all sorts of apps, I decided to take the time to create something more generic and to open source it. JDFPeekaboo was born!

What it does

The idea is pretty simple; JDFPeekaboo acts as a coordinator between a UIScrollView (or a subclass of UIScrollView, of course) and either a view at the top of the screen (that will move upwards, out of the way), a view at the bottom of the screen (that will move downwards, out of the way), or both. Typically, these might be a UINavigationBar and a UIToolbar respectively, but they don’t have to be; any UIView will do. As the user scrolls downwards, the top and bottom views are moved out of the way, giving them more screen real-estate for their content. Scrolling back up again brings them back into view.

By default, the top view is left slightly visible when it is minimised (so it’s about the size of the status bar), but this can be changed to make it bigger, smaller, or completely hidden.

JDFPeekaboo also fades out some of the stuff on your top view, because it looks a bit nicer (and to stop the ugliness if you choose to have your top view remain slightly visible when minimised). It automatically handles a UINavigationBar’s title and UIBarButtonItems (bar button items with custom views coming soon!). If there are other views that you also want dimmed, you can use the topViewItems property.

Here’s what it looks like in action:

How It Does It

JDFPeekaboo works by intercepting the scrollView’s delegate messages (which it sets up for when JDFPeekaboo’s scrollView is set). For that reason, you should avoid setting the scrollView’s delegate after setting it on JDFPeekaboo. If you do need to do so, you will need to set the scrollView on JDFPeekaboo again (otherwise, JDFPeekaboo will cease to work). Something like this:

// self.scrollView is the scrollView that `JDFPeekaboo` is tracking, but we need to change its delegate for some other reason
self.scrollView.delegate = someOtherThing;

// So now we need to set JDFPeekaboo's (self.scrollCoordinator) scrollView again
self.scrollCoordinator.scrollView = self.scrollView;

Using It

Using JDFPeekaboo is easy.

All you need to do is create it, tell it which scroll view to use, and tell it which are your top & bottom views. Like so:

// You need to keep a reference to it
 @property (nonatomic, strong) JDFPeekabooCoordinator *scrollCoordinator;

Then, set it up (say, in -viewDidLoad):

self.scrollCoordinator = [[JDFPeekabooCoordinator alloc] init];
self.scrollCoordinator.scrollView = self.scrollView;
self.scrollCoordinator.topView = self.navigationController.navigationBar;
self.scrollCoordinator.bottomView = self.navigationController.toolbar;

That’s all you need to do to get it working. There’s an option for the height of the top bar when it is minimised, and some convenience methods that allow you to minimise/maximise the views manually.

There are also some convenience methods for disabling (and re-enabling) JDFPeekaboo; useful for when you push another view controller onto your navigation controller, for example.

Where is it

You can find JDFPeekaboo here on GitHub, and it’s available as a CocoaPod.

If you have any suggestions please do open an issue on GitHub, or, even better, submit a pull request.