SetupAnimationHelper.java revision 1abddd9f6225298066094e20a6c29061b6af4590
1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.tv.common.ui.setup.animation;
18
19import android.animation.Animator;
20import android.animation.AnimatorListenerAdapter;
21import android.animation.AnimatorSet;
22import android.animation.ObjectAnimator;
23import android.animation.TypeEvaluator;
24import android.transition.Transition;
25import android.transition.TransitionSet;
26import android.view.Gravity;
27import android.view.View;
28import android.widget.ImageView;
29
30/**
31 * A helper class for setup animation.
32 */
33public final class SetupAnimationHelper {
34    public static final long DELAY_BETWEEN_SIBLINGS_MS = applyAnimationTimeScale(33);
35
36    private static final float ANIMATION_SCALE = 1.0f;
37
38    private static long sFragmentTransitionDuration;
39    private static int sFragmentTransitionDistance;
40
41    private SetupAnimationHelper() { }
42
43    /**
44     * Sets the duration of the fragment transition.
45     */
46    public static void setFragmentTransitionDuration(long duration) {
47        sFragmentTransitionDuration = duration;
48    }
49
50    /**
51     * Sets the distance of the fragment transition.
52     */
53    public static void setFragmentTransitionDistance(int distance) {
54        sFragmentTransitionDistance = distance;
55    }
56
57    public static class TransitionBuilder {
58        private int mSlideEdge = Gravity.START;
59        private int mDistance = sFragmentTransitionDistance;
60        private long mDuration = sFragmentTransitionDuration;
61        private int[] mParentIdForDelay;
62        private int[] mExcludeIds;
63
64        /**
65         * Sets the edge of the slide transition.
66         *
67         * @see android.transition.Slide#setSlideEdge
68         */
69        public TransitionBuilder setSlideEdge(int slideEdge) {
70            mSlideEdge = slideEdge;
71            return this;
72        }
73
74        /**
75         * Sets the duration of the transition.
76         */
77        public TransitionBuilder setDuration(long duration) {
78            mDuration = duration;
79            return this;
80        }
81
82        /**
83         * Sets the ID of the view whose descendants will perform delayed move.
84         *
85         * @see android.view.ViewGroup#isTransitionGroup
86         */
87        public TransitionBuilder setParentIdsForDelay(int[] parentIdForDelay) {
88            mParentIdForDelay = parentIdForDelay;
89            return this;
90        }
91
92        /**
93         * Sets the ID's of the views which will not be included in the transition.
94         */
95        public TransitionBuilder setExcludeIds(int[] excludeIds) {
96            mExcludeIds = excludeIds;
97            return this;
98        }
99
100        /**
101         * Builds and returns the {@link android.transition.Transition}.
102         */
103        public Transition build() {
104            FadeAndShortSlide transition = new FadeAndShortSlide(mSlideEdge, mParentIdForDelay);
105            transition.setDistance(mDistance);
106            transition.setDuration(mDuration);
107            if (mExcludeIds != null) {
108                for (int id : mExcludeIds) {
109                    transition.excludeTarget(id, true);
110                }
111            }
112            return transition;
113        }
114    }
115
116    /**
117     * Applies the animation scale to the given {@code animator}.
118     */
119    public static Animator applyAnimationTimeScale(Animator animator) {
120        if (animator instanceof AnimatorSet) {
121            for (Animator child : ((AnimatorSet) animator).getChildAnimations()) {
122                applyAnimationTimeScale(child);
123            }
124        }
125        if (animator.getDuration() > 0) {
126            animator.setDuration((long) (animator.getDuration() * ANIMATION_SCALE));
127        }
128        animator.setStartDelay((long) (animator.getStartDelay() * ANIMATION_SCALE));
129        return animator;
130    }
131
132    /**
133     * Applies the animation scale to the given {@code transition}.
134     */
135    public static Transition applyAnimationTimeScale(Transition transition) {
136        if (transition instanceof TransitionSet) {
137            TransitionSet set = (TransitionSet) transition;
138            int count = set.getTransitionCount();
139            for (int i = 0; i < count; ++i) {
140                applyAnimationTimeScale(set.getTransitionAt(i));
141            }
142        }
143        if (transition.getDuration() > 0) {
144            transition.setDuration((long) (transition.getDuration() * ANIMATION_SCALE));
145        }
146        transition.setStartDelay((long) (transition.getStartDelay() * ANIMATION_SCALE));
147        return transition;
148    }
149
150    /**
151     * Applies the animation scale to the given {@code time}.
152     */
153    public static long applyAnimationTimeScale(long time) {
154        return (long) (time * ANIMATION_SCALE);
155    }
156
157    /**
158     * Returns an animator which animate the source image of the {@link ImageView}.
159     *
160     * <p>The frame rate is 60 fps.
161     */
162    public static ObjectAnimator createFrameAnimator(ImageView imageView, int[] frames) {
163        return createFrameAnimatorWithDelay(imageView, frames, 0);
164    }
165
166    /**
167     * Returns an animator which animate the source image of the {@link ImageView} with start delay.
168     *
169     * <p>The frame rate is 60 fps.
170     */
171    public static ObjectAnimator createFrameAnimatorWithDelay(ImageView imageView, int[] frames,
172            long startDelay) {
173        ObjectAnimator animator = ObjectAnimator.ofInt(imageView, "imageResource", frames);
174        // Make it 60 fps.
175        animator.setDuration(frames.length * 1000 / 60);
176        animator.setInterpolator(null);
177        animator.setStartDelay(startDelay);
178        animator.setEvaluator(new TypeEvaluator<Integer>() {
179            @Override
180            public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
181                return startValue;
182            }
183        });
184        return animator;
185    }
186
187    /**
188     * Creates a fade out animator.
189     *
190     * @param view The view which will be animated.
191     * @param duration The duration of the animation.
192     * @param makeVisibleAfterAnimation If {@code true}, the view will become visible after the
193     * animation ends.
194     */
195    public static Animator createFadeOutAnimator(final View view, int duration,
196            boolean makeVisibleAfterAnimation) {
197        ObjectAnimator animator = ObjectAnimator.ofFloat(view, View.ALPHA, 1.0f, 0.0f);
198        if (makeVisibleAfterAnimation) {
199            animator.addListener(new AnimatorListenerAdapter() {
200                @Override
201                public void onAnimationEnd(Animator animation) {
202                    view.setAlpha(1.0f);
203                }
204            });
205        }
206        return animator;
207    }
208}
209