Screen shot showing part of the Pull My Beard sample app.

Featured sample: Pull My Beard

Published: August 14th, 2013

Download from GitHub

Take a tour of the Pull My Beard sample app

The Sample Apps page includes examples that demonstrate different aspects of Cascades and core development. You can download these apps, try them out, and even use the code in your own apps. This week, we take a closer look at the Pull My Beard app, which demonstrates some simple animation and touch interaction techniques.

What the app does

When you run this sample app, you'll see a picture of a stately gentleman with a luxurious beard. You can touch his beard and drag it downward. When you release his beard, it returns to its starting position. The movement of the beard is animated in both cases, and the app plays sounds to match the animation.

The beard is animated separately from the rest of the picture by using one ImageView for the beard and another one for the rest of the image. This way, we can animate the position of just the beard to get the effect we want.

Screen shot showing the Pull My Beard sample app.

Animating the beard

There are two animations that we want to look at in this app. One occurs when you touch and drag the beard downward, and the other occurs when you release the beard. The first isn't really an animation at all; we're really just listening for touch events, and when we detect one, we update the position of the beard image to reflect the new position of the touch. We'll talk more about how to listen for touch events and respond to them in the next section.

To animate the beard back to its starting position when it's released, we use the animations property. This is a list property that's part of VisualNode and its subclasses, so it's inherited by ImageView and available for us to use. We use this property to add a set of sequential animations that return the beard image to its original position. You'll notice that the animation appears to pause slightly just before it finishes. This pause occurs because we're also playing a "Thank you" sound when the entire animation sequence begins, and we want to line up the sound with the animation.

animations: [
    SequentialAnimation {
        id: resetBeard
        animations: [
            TranslateTransition {
                toY: 11
                duration: 400 * 0.7
            },
            TranslateTransition {
                toY: 13
                duration: 400 * 0.3
            },
            TranslateTransition {
                toY: 0
                duration: 400 * 0.1
            }
        ]
        onStarted: {
            // Play the "thank you" sound when the
            // animation starts
            pullMyBeardApp.playSound("thank_you.wav");
        }
    }
]

Responding to touch events

To listen for touch events, we can use the touch() signal. This signal is emitted by our beard ImageView when some type of touch event occurs on it (a touch down event, a touch move event, and so on), and it includes a parameter called event that describes what the touch event was. Depending on the type of touch event that occurred, we update our property values accordingly. For now, it's not really important that you understand what each property value means; we just want to show you an example of responding to different touch events.

onTouch: {
    // Disable implicit animations on the beard; this will make
    // the small movements more snappy
    translationControllerY.enabled = false;

    // Check for a press, if so, set the state variables we need
    if (event.isDown()) {
        resetBeard.stop();
        dy = event.windowY;
        playedAhh = false;

    // Check for a move.
    } else if (event.isMove()) {
        currentY = event.windowY - dy;

        // Check the drag limits.
        if (currentY > dragThreshold) {
            translationY = dragThreshold;

            // If we haven't already played the "aaaah" sound,
            // it's time to do so!
            if (! playedAhh) {
                pullMyBeardApp.playSound("aaaa.wav");
                playedAhh = true;
            }
        } else if (currentY < 0) {
            // Minimum drag threshold of the beard is zero
            // position
            translationY = 0;
            playedAhh = false;
        } else {
            // Within bounds, update position
            translationY = currentY;
        }
    } else if (event.isUp()) {
        // Beard was released, we call the release function
        releaseBeard();
    }

    // Re-enabling the implicit animations
    translationControllerY.enabled = true;
}

What's next?

This article highlights the animation features of the Pull My Beard app, so make sure you download the sample and explore the rest of the code. To learn more about the concepts that we discussed, you can read the Animations and Touch interaction documentation.