1 /*
2  * Copyright (C) 2016 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 
17 package com.android.systemui.animation;
18 
19 import android.graphics.Path;
20 import android.util.MathUtils;
21 import android.view.animation.AccelerateDecelerateInterpolator;
22 import android.view.animation.AccelerateInterpolator;
23 import android.view.animation.BounceInterpolator;
24 import android.view.animation.DecelerateInterpolator;
25 import android.view.animation.Interpolator;
26 import android.view.animation.LinearInterpolator;
27 import android.view.animation.PathInterpolator;
28 
29 /**
30  * Utility class to receive interpolators from
31  */
32 public class Interpolators {
33 
34     /*
35      * ============================================================================================
36      * Emphasized interpolators.
37      * ============================================================================================
38      */
39 
40     /**
41      * The default emphasized interpolator. Used for hero / emphasized movement of content.
42      */
43     public static final Interpolator EMPHASIZED = createEmphasizedInterpolator();
44 
45     /**
46      * The accelerated emphasized interpolator. Used for hero / emphasized movement of content that
47      * is disappearing e.g. when moving off screen.
48      */
49     public static final Interpolator EMPHASIZED_ACCELERATE = new PathInterpolator(
50             0.3f, 0f, 0.8f, 0.15f);
51 
52     /**
53      * The decelerating emphasized interpolator. Used for hero / emphasized movement of content that
54      * is appearing e.g. when coming from off screen
55      */
56     public static final Interpolator EMPHASIZED_DECELERATE = new PathInterpolator(
57             0.05f, 0.7f, 0.1f, 1f);
58 
59 
60     /*
61      * ============================================================================================
62      * Standard interpolators.
63      * ============================================================================================
64      */
65 
66     /**
67      * The standard interpolator that should be used on every normal animation
68      */
69     public static final Interpolator STANDARD = new PathInterpolator(
70             0.2f, 0f, 0f, 1f);
71 
72     /**
73      * The standard accelerating interpolator that should be used on every regular movement of
74      * content that is disappearing e.g. when moving off screen.
75      */
76     public static final Interpolator STANDARD_ACCELERATE = new PathInterpolator(
77             0.3f, 0f, 1f, 1f);
78 
79     /**
80      * The standard decelerating interpolator that should be used on every regular movement of
81      * content that is appearing e.g. when coming from off screen.
82      */
83     public static final Interpolator STANDARD_DECELERATE = new PathInterpolator(
84             0f, 0f, 0f, 1f);
85 
86     /*
87      * ============================================================================================
88      * Legacy
89      * ============================================================================================
90      */
91 
92     /**
93      * The default legacy interpolator as defined in Material 1. Also known as FAST_OUT_SLOW_IN.
94      */
95     public static final Interpolator LEGACY = new PathInterpolator(0.4f, 0f, 0.2f, 1f);
96 
97     /**
98      * The default legacy accelerating interpolator as defined in Material 1.
99      * Also known as FAST_OUT_LINEAR_IN.
100      */
101     public static final Interpolator LEGACY_ACCELERATE = new PathInterpolator(0.4f, 0f, 1f, 1f);
102 
103     /**
104      * The default legacy decelerating interpolator as defined in Material 1.
105      * Also known as LINEAR_OUT_SLOW_IN.
106      */
107     public static final Interpolator LEGACY_DECELERATE = new PathInterpolator(0f, 0f, 0.2f, 1f);
108 
109     /**
110      * Linear interpolator. Often used if the interpolator is for different properties who need
111      * different interpolations.
112      */
113     public static final Interpolator LINEAR = new LinearInterpolator();
114 
115     /*
116     * ============================================================================================
117     * Custom interpolators
118     * ============================================================================================
119     */
120 
121     public static final Interpolator FAST_OUT_SLOW_IN = LEGACY;
122     public static final Interpolator FAST_OUT_LINEAR_IN = LEGACY_ACCELERATE;
123     public static final Interpolator LINEAR_OUT_SLOW_IN = LEGACY_DECELERATE;
124 
125     /**
126      * Like {@link #FAST_OUT_SLOW_IN}, but used in case the animation is played in reverse (i.e. t
127      * goes from 1 to 0 instead of 0 to 1).
128      */
129     public static final Interpolator FAST_OUT_SLOW_IN_REVERSE =
130             new PathInterpolator(0.8f, 0f, 0.6f, 1f);
131     public static final Interpolator SLOW_OUT_LINEAR_IN = new PathInterpolator(0.8f, 0f, 1f, 1f);
132     public static final Interpolator ALPHA_IN = new PathInterpolator(0.4f, 0f, 1f, 1f);
133     public static final Interpolator ALPHA_OUT = new PathInterpolator(0f, 0f, 0.8f, 1f);
134     public static final Interpolator ACCELERATE = new AccelerateInterpolator();
135     public static final Interpolator ACCELERATE_DECELERATE = new AccelerateDecelerateInterpolator();
136     public static final Interpolator DECELERATE_QUINT = new DecelerateInterpolator(2.5f);
137     public static final Interpolator CUSTOM_40_40 = new PathInterpolator(0.4f, 0f, 0.6f, 1f);
138     public static final Interpolator ICON_OVERSHOT = new PathInterpolator(0.4f, 0f, 0.2f, 1.4f);
139     public static final Interpolator ICON_OVERSHOT_LESS = new PathInterpolator(0.4f, 0f, 0.2f,
140             1.1f);
141     public static final Interpolator PANEL_CLOSE_ACCELERATED = new PathInterpolator(0.3f, 0, 0.5f,
142             1);
143     public static final Interpolator BOUNCE = new BounceInterpolator();
144     /**
145      * For state transitions on the control panel that lives in GlobalActions.
146      */
147     public static final Interpolator CONTROL_STATE = new PathInterpolator(0.4f, 0f, 0.2f,
148             1.0f);
149 
150     /**
151      * Interpolator to be used when animating a move based on a click. Pair with enough duration.
152      */
153     public static final Interpolator TOUCH_RESPONSE =
154             new PathInterpolator(0.3f, 0f, 0.1f, 1f);
155 
156     /**
157      * Like {@link #TOUCH_RESPONSE}, but used in case the animation is played in reverse (i.e. t
158      * goes from 1 to 0 instead of 0 to 1).
159      */
160     public static final Interpolator TOUCH_RESPONSE_REVERSE =
161             new PathInterpolator(0.9f, 0f, 0.7f, 1f);
162 
163     /*
164      * ============================================================================================
165      * Functions / Utilities
166      * ============================================================================================
167      */
168 
169     /**
170      * Calculate the amount of overshoot using an exponential falloff function with desired
171      * properties, where the overshoot smoothly transitions at the 1.0f boundary into the
172      * overshoot, retaining its acceleration.
173      *
174      * @param progress a progress value going from 0 to 1
175      * @param overshootAmount the amount > 0 of overshoot desired. A value of 0.1 means the max
176      *                        value of the overall progress will be at 1.1.
177      * @param overshootStart the point in (0,1] where the result should reach 1
178      * @return the interpolated overshoot
179      */
getOvershootInterpolation(float progress, float overshootAmount, float overshootStart)180     public static float getOvershootInterpolation(float progress, float overshootAmount,
181             float overshootStart) {
182         if (overshootAmount == 0.0f || overshootStart == 0.0f) {
183             throw new IllegalArgumentException("Invalid values for overshoot");
184         }
185         float b = MathUtils.log((overshootAmount + 1) / (overshootAmount)) / overshootStart;
186         return MathUtils.max(0.0f,
187                 (float) (1.0f - Math.exp(-b * progress)) * (overshootAmount + 1.0f));
188     }
189 
190     /**
191      * Similar to {@link #getOvershootInterpolation(float, float, float)} but the overshoot
192      * starts immediately here, instead of first having a section of non-overshooting
193      *
194      * @param progress a progress value going from 0 to 1
195      */
getOvershootInterpolation(float progress)196     public static float getOvershootInterpolation(float progress) {
197         return MathUtils.max(0.0f, (float) (1.0f - Math.exp(-4 * progress)));
198     }
199 
200     // Create the default emphasized interpolator
createEmphasizedInterpolator()201     private static PathInterpolator createEmphasizedInterpolator() {
202         Path path = new Path();
203         // Doing the same as fast_out_extra_slow_in
204         path.moveTo(0f, 0f);
205         path.cubicTo(0.05f, 0f, 0.133333f, 0.06f, 0.166666f, 0.4f);
206         path.cubicTo(0.208333f, 0.82f, 0.25f, 1f, 1f, 1f);
207         return new PathInterpolator(path);
208     }
209 }
210