watchOS

WatchOS 2 Tutorial: Animations Using Groups

One of the most delightful videos of WWDC ’15 was the Layout and Animation Techniques for WatchKit. While not nearly as noteworthy as the new frameworks introduced, the new support for animations shows some much-needed progress allowing developers to make  watch user experiences as delightful as in iOS apps. They showed a variety of techniques, but the one that stood out the most for me was the use of empty groups as negative space in layouts. Using these empty groups, developers can now have more sophisticated layouts and transitions on the watch.

Here’s an example of using an empty group to animate a sliding label. See the finished projects in Swift and Objective-C.

watch animation

Let’s look at the underlying storyboard:

storyboard layout animation

Here’s what actually happening:

storyboard elements

There’s an underlying group that has an image, another group (used as a spacer), and a label layed out horizontally inside of it.  When the interface first loads, all you see is the image because the label is offscreen (and the group is invisible with nothing inside of it). Using an outlet to the spacer group, we can change the width of it to zero and bring the label sliding in next to the image using this code:

//Swift
@IBAction func animate() {
    
    animateWithDuration(0.3, animations: {
        self.spacerGroup.setWidth(0)
    })
    
}

@IBAction func reset() {
    self.spacerGroup.setWidth(100)
//Objective-C
- (IBAction)animate {
    
    [self animateWithDuration:0.3 animations:^{
        [self.spacerGroup setWidth:0];
    }];
    
}

- (IBAction)reset {
    [self.spacerGroup setWidth:100];
}

The same concept can be used to animate a moving button. Here’s an example where you can see a button moving from the top to the bottom of the screen. I suspect that they do something similar for the button animation in the Apple Watch Workout app when it’s transitioning from the table view to the starting workout screen.

moving button

Here’s the code to get this working:

//Swift
@IBOutlet var animateButton: WKInterfaceButton!
@IBOutlet var buttonSpacerGroup: WKInterfaceGroup!
var buttonMoved: Bool!

@IBAction func animateMovingButton() {
    if (buttonMoved != true) {
        animateWithDuration(0.3, animations: {
            self.buttonSpacerGroup.setHeight(100)
        })
        
        buttonMoved = true
        animateButton.setTitle("Reset")
    } else {
        animateWithDuration(0.3, animations: {
            self.buttonSpacerGroup.setHeight(0)
        })
        
        buttonMoved = false
        animateButton.setTitle("Animate!")
    }
}

//Objective-C

@property (unsafe_unretained, nonatomic) IBOutlet WKInterfaceGroup *buttonSpacerGroup;
@property (unsafe_unretained, nonatomic) IBOutlet WKInterfaceButton *animateButton;
@property (assign, nonatomic) BOOL buttonMoved;

- (IBAction)animateMovingButton {
    
    if (!self.buttonMoved) {
        [self animateWithDuration:0.3 animations:^{
            [self.buttonSpacerGroup setHeight:100];
        }];
        self.buttonMoved = YES;
        [self.animateButton setTitle:@"Reset"];
    } else {
        [self animateWithDuration:0.3 animations:^{
            [self.buttonSpacerGroup setHeight:0];
        }];
        self.buttonMoved = NO;
        [self.animateButton setTitle:@"Animate!"];
    }   
}

In our storyboard, we originally set the height of the buttonSpacerGroup to 0. When the user presses the button, this height changes to 100 and the button is animated moving down the screen. This is reminiscent of animating constraint changes in iOS. Now we can do it on the Watch too!

Apple has added some cool built-in animations using animateWithDuration. The main thing to watch out for is that you don’t go too crazy with the animations. These ones are pretty simple, but the more complex the layout is, the more animations can impact performance. Apple recommends that you place all animations in one animation block to improve performance.

2 thoughts on “WatchOS 2 Tutorial: Animations Using Groups

  1. I’m really enjoying your tuts Kristina. Thanks for making them. Could you use the foursquare example to push the text all the way off the screen and rerun the animation? That would be a very useful effect for watchOS..

    David

    1. Thanks David! Glad to hear!

      You know, I tried doing exactly that for the reset function on the Foursquare example, but it didn’t animate at all. I suspect that the WatchKit team didn’t enable animations for a shrinking width (but I could be wrong).

Leave a Reply