• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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 package com.android.launcher3.anim;
17 
18 import android.content.Context;
19 
20 import androidx.dynamicanimation.animation.DynamicAnimation.OnAnimationEndListener;
21 import androidx.dynamicanimation.animation.FlingAnimation;
22 import androidx.dynamicanimation.animation.FloatPropertyCompat;
23 import androidx.dynamicanimation.animation.SpringAnimation;
24 import androidx.dynamicanimation.animation.SpringForce;
25 
26 import com.android.launcher3.R;
27 import com.android.launcher3.util.DynamicResource;
28 import com.android.systemui.plugins.ResourceProvider;
29 
30 /**
31  * Given a property to animate and a target value and starting velocity, first apply friction to
32  * the fling until we pass the target, then apply a spring force to pull towards the target.
33  */
34 public class FlingSpringAnim {
35 
36     private final FlingAnimation mFlingAnim;
37     private SpringAnimation mSpringAnim;
38     private final boolean mSkipFlingAnim;
39 
40     private float mTargetPosition;
41 
FlingSpringAnim(K object, Context context, FloatPropertyCompat<K> property, float startPosition, float targetPosition, float startVelocity, float minVisChange, float minValue, float maxValue, float springVelocityFactor, OnAnimationEndListener onEndListener)42     public <K> FlingSpringAnim(K object, Context context, FloatPropertyCompat<K> property,
43             float startPosition, float targetPosition, float startVelocity, float minVisChange,
44             float minValue, float maxValue, float springVelocityFactor,
45             OnAnimationEndListener onEndListener) {
46         ResourceProvider rp = DynamicResource.provider(context);
47         float damping = rp.getFloat(R.dimen.swipe_up_rect_xy_damping_ratio);
48         float stiffness = rp.getFloat(R.dimen.swipe_up_rect_xy_stiffness);
49         float friction = rp.getFloat(R.dimen.swipe_up_rect_xy_fling_friction);
50 
51         mFlingAnim = new FlingAnimation(object, property)
52                 .setFriction(friction)
53                 // Have the spring pull towards the target if we've slowed down too much before
54                 // reaching it.
55                 .setMinimumVisibleChange(minVisChange)
56                 .setStartVelocity(startVelocity)
57                 .setMinValue(minValue)
58                 .setMaxValue(maxValue);
59         mTargetPosition = targetPosition;
60 
61         // We are already past the fling target, so skip it to avoid losing a frame of the spring.
62         mSkipFlingAnim = startPosition <= minValue && startVelocity < 0
63                 || startPosition >= maxValue && startVelocity > 0;
64 
65         mFlingAnim.addEndListener(((animation, canceled, value, velocity) -> {
66             mSpringAnim = new SpringAnimation(object, property)
67                     .setStartValue(value)
68                     .setStartVelocity(velocity * springVelocityFactor)
69                     .setSpring(new SpringForce(mTargetPosition)
70                             .setStiffness(stiffness)
71                             .setDampingRatio(damping));
72             mSpringAnim.addEndListener(onEndListener);
73             mSpringAnim.animateToFinalPosition(mTargetPosition);
74         }));
75     }
76 
getTargetPosition()77     public float getTargetPosition() {
78         return mTargetPosition;
79     }
80 
updatePosition(float startPosition, float targetPosition)81     public void updatePosition(float startPosition, float targetPosition) {
82         mFlingAnim.setMinValue(Math.min(startPosition, targetPosition))
83                 .setMaxValue(Math.max(startPosition, targetPosition));
84         mTargetPosition = targetPosition;
85         if (mSpringAnim != null) {
86             mSpringAnim.animateToFinalPosition(mTargetPosition);
87         }
88     }
89 
start()90     public void start() {
91         mFlingAnim.start();
92         if (mSkipFlingAnim) {
93             mFlingAnim.cancel();
94         }
95     }
96 
end()97     public void end() {
98         mFlingAnim.cancel();
99         if (mSpringAnim.canSkipToEnd()) {
100             mSpringAnim.skipToEnd();
101         }
102     }
103 }
104