bdunagan

fill the void - bdunagan

29 Sep 2009
Syncing Arrows in an iPhone App

My last post illustrated how to add syncing arrows to a Mac application, like iPhoto and iTunes have. But what adding that user feedback to an iPhone app? Don't worry; it's even easier, thanks to Core Animation. In fact, there are multiple paths to those rotating arrows: an image array and a simple rotation transform.

In both cases, we'll use a custom UITableViewCell to drive the animation, unlike the model-driven approach we used on the Mac. See my custom UITableViewCell post for a tutorial.

Animate using image array

UIImageView has three properties available to facilitate animations: animationDuration, animationImages, and animationRepeatCount. We can use these to easily incorporate the six iPhoto arrow images (see the Mac syncing arrows post) into our custom UITableViewCell. For indefinite animation (which we want), set animationRepeatCount to zero, according to Apple's documentation. Then, after setting the duration, we simply start the animation.

// Animate using image array.
syncIconView.animationImages = [NSArray arrayWithObjects:
    [[[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"syncing_arrows1" ofType:@"png"]] autorelease], 
    [[[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"syncing_arrows2" ofType:@"png"]] autorelease], 
    [[[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"syncing_arrows3" ofType:@"png"]] autorelease], 
    [[[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"syncing_arrows4" ofType:@"png"]] autorelease], 
    [[[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"syncing_arrows5" ofType:@"png"]] autorelease], 
    [[[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"syncing_arrows6" ofType:@"png"]] autorelease], 
    nil];
syncIconView.animationDuration = interval;
syncIconView.animationRepeatCount = 0;
[syncIconView startAnimating];

Animate using rotation transform

Instead of leveraging UIImageView-specific methods, we utilize the iPhone's layer-backed UIViews and create a CAAnimation, with a rotation transform. To match the array animation, we make the toValue equal to pi radians (180 degrees). Unlike the array animation, we cannot supply a specific argument to have the animation repeat indefinitely, so we just assign a really large value. (Let me know if there is a better workaround.) Finally, we add the new animation to the UIImageView's layer.

// Animate using rotate transform.
CABasicAnimation* rotateAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
rotateAnimation.toValue = [NSNumber numberWithFloat:M_PI];
rotateAnimation.duration = interval;
rotateAnimation.repeatCount = 1e100;
[syncIconView.layer addAnimation:rotateAnimation forKey:@"rotateAnimation"];

Results

The difference between the two animations is quite striking. At a small duration (around .3s), the array animation looks fine without comparison. The animation is almost imperceptibly jumpy but is, again, just fine. However, a side-by-side comparison of it to the rotation transform animation reveals the stark contrast between the two approaches. The latter shows how amazing Core Animation makes the UI; it's magic pixie dust. I committed a sample project (10.5, Xcode 3.1.4) to Google Code. Check it out in SVN, run it, and compare "Array at 1.00s" with "Rotate at 1.00s". The rotate transform wins. As does Core Animation.

Previous LinkedIn Twitter GitHub Email Next