In all the samples we have presented so far, we followed very common pattern when defining transitions: assigning transition keys and creating transitions happened within one ComponentSpec. However, there are situations where this is not the case: transition key is assigned within ComponentSpec, while transitions themselves are defined in another.

If you try to do everything exactly how we did it up until now it will not work. It will simply look like there are no transitions defined.

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
26
27
28
29
30
31
32
33
34
35
36
37
/**
 * MyComponentSpec.java
 */
@LayoutSpec
class MyComponentSpec {

    @OnCreateLayout
    static Component onCreateLayout(ComponentContext c) {
        return AnotherComponent.create(c).build();
    }

    @OnCreateLayout
    static Transition onCreateTransition(ComponentContext c) {
        return Transition.create("square")
            .animate(AnimatedProperties.X);
    }
}

/**
 * AnotherComponentSpec.java
 */
@LayoutSpec
class AnotherComponentSpec {

    @OnCreateLayout
    static Component onCreateLayout(ComponentContext c, @State boolean toLeft) {
        return Column.create(c)
            .child(
                Rect.create(c)
                    .color(YELLOW)
                    .widthDip(80)
                    .heightDip(80)
                    .transitionKey("square"))
            .alignItems(toRight ? YogaAlign.FLEX_END : YogaAlign.FLEX_START)
            .build();
    }
}

The reason is that, by default, transition keys are only visible within the scope of the component spec where it is used. This “visibility” of transition keys is determined by TransitionKeyType. There are two options:

  • LOCAL - the default type, only visible within ComponentSpec where it is used
  • GLOBAL - makes a transition key visible through the whole ComponentTree. The drawback here is that the keys should be unique within the tree. Thus it usually takes an extra effort to use several component of the same type that assign GLOBAL transition keys within one tree and avoid transition keys collisions.

Note that Litho throws an exception when a transition keys collision occurs, which may not be trivial to debug and resolve in case of GLOBAL transition keys. Thus we encourage you to use LOCAL transition keys and assign transition keys within the same Spec that defines transitions that target those keys.

There are two steps to take to change transition key type:

  1. Use Component.Builder#transitionKeyType() when assigning a key to a Component.
  2. When creating a Transition use a version of Transition.create() that takes TransitionKeyType argument along with the key itself.

Here is how we would fix the sample using TransitionKeyType.GLOBAL (lines 14, 33):

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
26
27
28
29
30
31
32
33
34
35
36
37
38
/**
 * MyComponentSpec.java
 */
@LayoutSpec
class MyComponentSpec {

    @OnCreateLayout
    static Component onCreateLayout(ComponentContext c) {
        return AnotherComponent.create(c).build();
    }

    @OnCreateLayout
    static Transition onCreateTransition(ComponentContext c) {
        return Transition.create(Transition.TransitionKeyType.GLOBAL, "square")
            .animate(AnimatedProperties.X);
    }
}

/**
 * AnotherComponentSpec.java
 */
@LayoutSpec
class AnotherComponentSpec {

    @OnCreateLayout
    static Component onCreateLayout(ComponentContext c, @State boolean toLeft) {
        return Column.create(c)
            .child(
                Rect.create(c)
                    .color(YELLOW)
                    .widthDip(80)
                    .heightDip(80)
                    .transitionKeyType(Transition.TransitionKeyType.GLOBAL)
                    .transitionKey("square"))
            .alignItems(toRight ? YogaAlign.FLEX_END : YogaAlign.FLEX_START)
            .build();
    }
}

Edit on GitHub