Fickle Bits

You're doing it wrong.

Making a UIButton Flip Over

If you’ve used the iPod app on the iPhone, you’ve probably seen an interesting trick when switching from album art to the track listing: the button in the top right corner flips over synchronized with the flip animation of the main view.

I wanted to achieve a similar effect for the iPhone app that I’m building, Deli Radio (app store link).

If you’ve ever struggled with the flip transitions before, you probably know how finicky it can be to get it all working. The best way to set it up is to have a parent view contain both views that you want to swap, and set the animation transition type on that view.

For a button (either in the navigation bar or elsewhere) we’d need to introduce a parent view to achieve this effect. This is how I achieved the effect.

First, I had two images I wanted to use for my UIBarButtonItem.

I wanted this to be easily reusable (since I need to do this in more than one place in this application), so I created a category method on UIButton.

It may look strange that a UIButton class method returns a UIView instance, but we need to have a container view to base the animations off of.

Here is the implementation:

I am using a little-known technique of setting associated objects using objc_setAssociatedObject(...). This uses the runtime to attach state to an existing class without needing to subclass.

Now that you understand how it is all setup, the block body will now make sense:

Usage is really easy. I just created a bar button item with a custom view, and was done.

1
2
3
4
5
6
7
8
9
10
11
12
13
UIImage *firstImage = [UIImage imageNamed:@"btn-info.png"];
UIImage *secondImage = [UIImage imageNamed:@"btn-images.png"];
UIView *container = [UIButton flipButtonWithFirstImage:firstImage
secondImage:secondImage
firstTransition:UIViewAnimationTransitionFlipFromRight
secondTransition:UIViewAnimationTransitionFlipFromLeft
animationCurve:UIViewAnimationCurveEaseInOut
duration:0.8
target:self
selector:@selector(flipContent)];
self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc]
initWithCustomView:container] autorelease];

The effect can be seen below.

Note that the flip effect on the main view is achieved separately, but the 2 strategies share identical values for the animation, so the flip transition types match, as well as the duration & animation curve.

The code for this can be seen in the ChaiOneUI project on Github.

iOS

Comments