/* * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ package com.facebook.litho; import java.util.ArrayList; import com.facebook.litho.animation.AnimatedComponent; import com.facebook.litho.animation.AnimatedProperty; import com.facebook.litho.animation.AnimationBinding; import com.facebook.litho.animation.AppearingComponent; import com.facebook.litho.animation.ChangingComponent; import com.facebook.litho.animation.ComponentProperty; import com.facebook.litho.animation.DisappearingComponent; import com.facebook.litho.animation.DimensionValue; import com.facebook.litho.animation.FloatValue; import com.facebook.litho.animation.RuntimeValue; import com.facebook.litho.animation.SpringTransition; import com.facebook.litho.animation.TransitionAnimationBinding; /** * Defines how a property on a component should animate as it changes, allowing you to optionally * define appear-from values for appear animations and disappear-to values for disappear animations. */ public class Transition { private static final TransitionAnimator DEFAULT_ANIMATOR = new SpringTransitionAnimator(); /** * Class that knows how to create a {@link TransitionAnimationBinding} given a * {@link ComponentProperty}. This can be used to customize the type of animation using * {@link Builder#animator}. */ public interface TransitionAnimator { /** * @return a {@link TransitionAnimationBinding} for the given {@link ComponentProperty} that * will animate the change in value on this property. */ TransitionAnimationBinding createAnimation(ComponentProperty property); } /** * Creates a Transition for the given property on the component with the given key. */ public static Transition.Builder create(String key) { return new Transition.Builder(key); } /** * Creates a set of {@link Transition}s. */ public static TransitionSet createSet(Transition.Builder... transitions) { return new TransitionSet(transitions); } private final String mTransitionKey; private final AnimatedProperty mAnimatedProperty; private final TransitionAnimator mTransitionAnimator; private final RuntimeValue mAppearFrom; private final RuntimeValue mDisappearTo; public Transition( String transitionKey, AnimatedProperty animatedProperty, TransitionAnimator transitionAnimator, RuntimeValue appearFrom, RuntimeValue disappearTo) { mTransitionKey = transitionKey; mAnimatedProperty = animatedProperty; mTransitionAnimator = transitionAnimator; mAppearFrom = appearFrom; mDisappearTo = disappearTo; } boolean hasAppearAnimation() { return mAppearFrom != null; } boolean hasDisappearAnimation() { return mDisappearTo != null; } String getTransitionKey() { return mTransitionKey; } AnimationBinding createAppearAnimation() { if (!hasAppearAnimation()) { throw new RuntimeException( "Trying to create an appear animation when no from value was provided!"); } final AppearingComponent component = new AppearingComponent(mTransitionKey); final ComponentProperty property = new AutoTransitionComponentProperty( component, mAnimatedProperty); final TransitionAnimationBinding animation = mTransitionAnimator.createAnimation(property); animation.addAppearFromValue(property, mAppearFrom); return animation; } AnimationBinding createDisappearAnimation() { if (!hasDisappearAnimation()) { throw new RuntimeException( "Trying to create an disappear animation when no to value was provided!"); } final DisappearingComponent component = new DisappearingComponent(mTransitionKey); final ComponentProperty property = new AutoTransitionComponentProperty( component, mAnimatedProperty); final TransitionAnimationBinding animation = mTransitionAnimator.createAnimation(property); animation.addDisappearToValue(property, mDisappearTo); return animation; } AnimationBinding createChangeAnimation() { final ChangingComponent component = new ChangingComponent(mTransitionKey); final ComponentProperty property = new AutoTransitionComponentProperty( component, mAnimatedProperty); final TransitionAnimationBinding animation = mTransitionAnimator.createAnimation(property); return animation; } public static class Builder { private final String mKey; private final ArrayList<Transition> mBuiltTransitions = new ArrayList<>(); private AnimatedProperty mAnimatedProperty; private TransitionAnimator mTransitionAnimator = DEFAULT_ANIMATOR; private RuntimeValue mAppearFrom; private RuntimeValue mDisappearTo; Builder(String key) { mKey = key; } public Builder animate(AnimatedProperty property) { maybeCommitCurrentBuilder(); mAnimatedProperty = property; return this; } /** * Use to define the {@link TransitionAnimator} that drives the animation. The default is a * spring. */ public Builder animator(TransitionAnimator animator) { mTransitionAnimator = animator; return this; } /** * Define where appear animations should start from. * * @see FloatValue * @see DimensionValue */ public Builder appearFrom(RuntimeValue value) { mAppearFrom = value; return this; } /** * Define where disappear animations should end at. * * @see FloatValue * @see DimensionValue */ public Builder disappearTo(RuntimeValue value) { mDisappearTo = value; return this; } /** * Define a constant value where appear animations should start from. */ public Builder appearFrom(float value) { mAppearFrom = new FloatValue(value); return this; } /** * Define a constant value where disappear animations should end at. */ public Builder disappearTo(float value) { mDisappearTo = new FloatValue(value); return this; } ArrayList<Transition> getTransitions() { maybeCommitCurrentBuilder(); return mBuiltTransitions; } private void maybeCommitCurrentBuilder() { if (mAnimatedProperty == null) { return; } mBuiltTransitions.add( new Transition( mKey, mAnimatedProperty, mTransitionAnimator, mAppearFrom, mDisappearTo)); mAnimatedProperty = null; mTransitionAnimator = DEFAULT_ANIMATOR; mAppearFrom = null; mDisappearTo = null; } } private static class AutoTransitionComponentProperty extends ComponentProperty { AutoTransitionComponentProperty( AnimatedComponent animatedComponent, AnimatedProperty property) { super(animatedComponent, property); } } /** * Creates spring-driven animations. */ public static class SpringTransitionAnimator implements TransitionAnimator { @Override public TransitionAnimationBinding createAnimation(ComponentProperty property) { return new SpringTransition(property); } } }