Staggers, Sequences, and Parallel Sets

In order to make it possible to implement more complex transition animations, that may involve multiple components, Litho supports creating sets of animations that can run in parallel, in sequence, or on a stagger.

1
2
3
4
5
6
7
8
@OnCreateTransition
static Transition onCreateTransition(ComponentContext c) {
    return Transition.stagger(
        100,
        Transition.create("yellow").animate(AnimatedProperties.Y),
        Transition.create("blue").animate(AnimatedProperties.Y),
        Transition.create("purple").animate(AnimatedProperties.Y));
}

Sequences and staggers also support interrupting behavior, trying to preserve the guarantee that a component will never jump and will always end up in the correct final position.

Delays

Additionally, Litho provides .delay() API that follows the same pattern. These sets and delayed transitions can also be nested within each other, e.g. you can have a stagger of parallel animation sets.

1
2
3
4
5
6
7
8
9
@OnCreateTransition
static Transition onCreateTransitionDelayed(ComponentContext c) {
    return Transition.parallel(
        Transition.sequence(
            Transition.create("yellow").animate(AnimatedProperties.Y),
            Transition.create("blue").animate(AnimatedProperties.Y)),
        Transition.delay(3000,
            Transition.create("purple").animate(AnimatedProperties.Y)));
}

Animators

By default, all transitions in Litho run by a spring Animator with default configurations. You can tune the parameters of this spring by creating another Animator using Transition.springWith() or you can choose to use timing-based Animators that could be created with Transition.timing(). To change the Animator use .animator() builder setting when creating your transition (lines 6, 9, 12):

1
2
3
4
5
6
7
8
9
10
11
12
13
@OnCreateTransition
static Transition onCreateTransition(ComponentContext c) {
    return Transition.parallel(
        Transition.create("yellow")
            .animate(AnimatedProperties.Y)
            .animator(Transition.springWithConfig(120, 12)),
        Transition.create("blue")
            .animate(AnimatedProperties.Y)
            .animator(Transition.timing(1000)),
        Transition.create("purple")
            .animate(AnimatedProperties.Y)
            .animator(Transition.timing(1000, new BounceInterpolator())));
}

Transition end callback

A listener can be added to receive a callback when an individual transition has ended. This is done through the Litho event dispatcher. See Events overview. The TransitionEndEvent will be called with the transition key and the specific AnimatedProperty that has been animated for that key. If multiple AnimatedPropertys are added to the same transition, and all of them run at the same time, a callback will be excecuted for each one of those.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@LayoutSpec
public class ThisComponentSpec {
    ...
    @OnEvent(TransitionEndEvent.class)
    static void onTransitionEndEvent(
        ComponentContext c,
        @FromEvent String transitionKey,
        @FromEvent AnimatedProperty property) {
        // Handle transition end here
    }
    @OnCreateTransition
    static Transition onCreateTransition(ComponentContext c) {
        return Transition.stagger(
            100,
            Transition.create("yellow")
                .animate(AnimatedProperties.Y)
                .transitionEndHandler(ThisComponent.onTransitionEndEvent(c)),
            Transition.create("blue")
                .animate(AnimatedProperties.Y)
                .transitionEndHandler(ThisComponent.onTransitionEndEvent(c)),
            Transition.create("purple")
                .animate(AnimatedProperties.Y)
                .transitionEndHandler(ThisComponent.onTransitionEndEvent(c)));
    }
}

You can also add the transition end handler to the Transition.allLayout() and the same logic applies.

1
2
3
4
@OnCreateTransition
static Transition onCreateTransition(ComponentContext c) {
    return Transition.allLayout().transitionEndHandler(ThisComponent.onTransitionEndEvent(c));
}

Edit on GitHub