Sep 11, 2010

Floating View’s on My Mind Grapes

I had another post I was working on about iPad’s Photos app and its pinch-to-expand design, but then I had a conversation at work the other day and it got all up in my mind grapes. The Photos app will have to wait.

iOS’s “push” animation is fantastic. It gives the user a sense of hierarchy within the app and communicates the movement of state and information. Usually, the push moves the entire visible view to the left and moves the next view in from the right. But someone asked me if it was possible to keep a view in place while everything else gets pushed.

I don’t know that I’ve seen any app that does it, but it makes some sense for certain cases:

  •  You have a header view that is always at the top in some multi-step flow. It could improve the cohesiveness (cohesivity?) of the flow if you could keep that header always there, even during pushes.
  •  You have a common control like a search bar that’s always present. It seems silly, and maybe even distracting, to continually push it. Just let it be.
  •  …and probably some other cases.

So it could be a viable design choice. (Obligatory aside: don’t go breaking the HIG unless you have a damn good reason. Every time someone does something unnecessarily custom, Jonathan Ive kills a puppy. Most of Apple’s designers are worlds better than you. Use their stuff if at all possible.)

How would we implement the thing?

My initial thought involved doing the whole push animation myself. I’d grab the next view (or probably a bitmap representation of it), animate my current view to the left, the new view in from the right, and keep the floating view in the same place. And then once the animation had finished, I’d present the new view controller without an animation.

But that’s a lot of work and I’m lazy. It also has problems with not animating the change in the navigation item, -viewWill/DidAppear: being told they weren’t animated when they really kinda were, etc.

Then I realized I was overcomplicating the problem. The push animation happens in the UINavigationController, so if the floating view wasn’t in the UINavigationController, it wouldn’t be pushed. It’s just a matter of moving the floating view up in the view hierarchy before doing the push animation:

And moving it back down to its rightful place after the push animation finishes:

It’s really almost that easy. The only troublesome bit is that UIWindow’s coordinate systems aren’t transformed when the device rotates; it just applies a transform to its subviews. So we have to do a little bit of manual view transformation when moving to/from the window so that it doesn’t get all crazy.

That leaves us with a nice little category on UIView:

I’ve uploaded the code and a little sample app over at Github.

Feel free to send in any apps or UIs you’d like me to attempt to deconstruct!

Navigate
About

Mostly I work on GitHub for Mac. Mostly.

twitter / github