diff options
author | Jorim Jaggi <jjaggi@google.com> | 2014-05-12 23:29:10 +0200 |
---|---|---|
committer | Jorim Jaggi <jjaggi@google.com> | 2014-05-13 17:27:22 +0200 |
commit | 87cd5e71ec087e191b8baaa8913a878f92d4e10d (patch) | |
tree | 831e682598f7a5924b0e73b4272f4b296ec6c32a /packages/SystemUI/src | |
parent | 6dbae589731e9594b6e3c15dfc26797d9b6cda0c (diff) | |
download | frameworks_base-87cd5e71ec087e191b8baaa8913a878f92d4e10d.zip frameworks_base-87cd5e71ec087e191b8baaa8913a878f92d4e10d.tar.gz frameworks_base-87cd5e71ec087e191b8baaa8913a878f92d4e10d.tar.bz2 |
Improve quick settings fling/expand animation.
Change-Id: I507970ad2d22712a140f2107b62e689c2f3d7d6e
Diffstat (limited to 'packages/SystemUI/src')
-rw-r--r-- | packages/SystemUI/src/com/android/systemui/statusbar/FlingAnimationUtils.java | 129 | ||||
-rw-r--r-- | packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java | 13 |
2 files changed, 133 insertions, 9 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/FlingAnimationUtils.java b/packages/SystemUI/src/com/android/systemui/statusbar/FlingAnimationUtils.java new file mode 100644 index 0000000..0606a94 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/FlingAnimationUtils.java @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.systemui.statusbar; + +import android.animation.ValueAnimator; +import android.content.Context; +import android.view.animation.AnimationUtils; +import android.view.animation.Interpolator; +import android.view.animation.PathInterpolator; + +/** + * Utility class to calculate general fling animation when the finger is released. + */ +public class FlingAnimationUtils { + + private static final float LINEAR_OUT_SLOW_IN_Y2 = 0.35f; + private static final float MAX_LENGTH_SECONDS = 0.4f; + private static final float MIN_VELOCITY_DP_PER_SECOND = 250; + + /** + * Crazy math. http://en.wikipedia.org/wiki/B%C3%A9zier_curve + */ + private static final float LINEAR_OUT_SLOW_IN_START_GRADIENT = 1/LINEAR_OUT_SLOW_IN_Y2; + + private Interpolator mLinearOutSlowIn; + private Interpolator mFastOutSlowIn; + private float mMinVelocityPxPerSecond; + + public FlingAnimationUtils(Context ctx) { + mLinearOutSlowIn = new PathInterpolator(0, 0, LINEAR_OUT_SLOW_IN_Y2, 1); + mFastOutSlowIn + = AnimationUtils.loadInterpolator(ctx, android.R.interpolator.fast_out_slow_in); + mMinVelocityPxPerSecond + = MIN_VELOCITY_DP_PER_SECOND * ctx.getResources().getDisplayMetrics().density; + } + + /** + * Applies the interpolator and length to the animator, such that the fling animation is + * consistent with the finger motion. + * + * @param animator the animator to apply + * @param currValue the current value + * @param endValue the end value of the animator + * @param velocity the current velocity of the motion + */ + public void apply(ValueAnimator animator, float currValue, float endValue, float velocity) { + float diff = Math.abs(endValue - currValue); + float velAbs = Math.abs(velocity); + float durationSeconds = LINEAR_OUT_SLOW_IN_START_GRADIENT * diff / velAbs; + if (durationSeconds <= MAX_LENGTH_SECONDS) { + animator.setInterpolator(mLinearOutSlowIn); + } else if (velAbs >= mMinVelocityPxPerSecond) { + + // Cross fade between fast-out-slow-in and linear interpolator with current velocity. + durationSeconds = MAX_LENGTH_SECONDS; + VelocityInterpolator velocityInterpolator + = new VelocityInterpolator(durationSeconds, velAbs, diff); + InterpolatorInterpolator superInterpolator = new InterpolatorInterpolator( + velocityInterpolator, mLinearOutSlowIn, mLinearOutSlowIn); + animator.setInterpolator(superInterpolator); + } else { + + // Just use a normal interpolator which doesn't take the velocity into account. + durationSeconds = MAX_LENGTH_SECONDS; + animator.setInterpolator(mFastOutSlowIn); + } + animator.setDuration((long) (durationSeconds * 1000)); + } + + /** + * An interpolator which interpolates two interpolators with an interpolator. + */ + private static final class InterpolatorInterpolator implements Interpolator { + + private Interpolator mInterpolator1; + private Interpolator mInterpolator2; + private Interpolator mCrossfader; + + InterpolatorInterpolator(Interpolator interpolator1, Interpolator interpolator2, + Interpolator crossfader) { + mInterpolator1 = interpolator1; + mInterpolator2 = interpolator2; + mCrossfader = crossfader; + } + + @Override + public float getInterpolation(float input) { + float t = mCrossfader.getInterpolation(input); + return (1 - t) * mInterpolator1.getInterpolation(input) + + t * mInterpolator2.getInterpolation(input); + } + } + + /** + * An interpolator which interpolates with a fixed velocity. + */ + private static final class VelocityInterpolator implements Interpolator { + + private float mDurationSeconds; + private float mVelocity; + private float mDiff; + + private VelocityInterpolator(float durationSeconds, float velocity, float diff) { + mDurationSeconds = durationSeconds; + mVelocity = velocity; + mDiff = diff; + } + + @Override + public float getInterpolation(float input) { + float time = input * mDurationSeconds; + return time * mVelocity / mDiff; + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index 6132ed2..f19ce97 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -32,6 +32,7 @@ import android.widget.LinearLayout; import com.android.systemui.R; import com.android.systemui.statusbar.ExpandableView; +import com.android.systemui.statusbar.FlingAnimationUtils; import com.android.systemui.statusbar.GestureRecorder; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.stack.NotificationStackScrollLayout; @@ -53,8 +54,6 @@ public class NotificationPanelView extends PanelView implements private int mNotificationTopPadding; private boolean mAnimateNextTopPaddingChange; - private Interpolator mExpansionInterpolator; - private int mTrackingPointer; private VelocityTracker mVelocityTracker; private boolean mTracking; @@ -78,6 +77,7 @@ public class NotificationPanelView extends PanelView implements private int mStackScrollerIntrinsicPadding; private boolean mQsExpansionEnabled = true; private ValueAnimator mQsExpansionAnimator; + private FlingAnimationUtils mFlingAnimationUtils; public NotificationPanelView(Context context, AttributeSet attrs) { super(context, attrs); @@ -115,8 +115,7 @@ public class NotificationPanelView extends PanelView implements mNotificationTopPadding = getResources().getDimensionPixelSize( R.dimen.notifications_top_padding); mMinStackHeight = getResources().getDimensionPixelSize(R.dimen.collapsed_stack_height); - mExpansionInterpolator = AnimationUtils.loadInterpolator( - getContext(), android.R.interpolator.fast_out_slow_in); + mFlingAnimationUtils = new FlingAnimationUtils(getContext()); } @Override @@ -435,13 +434,9 @@ public class NotificationPanelView extends PanelView implements } } private void flingSettings(float vel, boolean expand) { - - // TODO: Actually use velocity. - float target = expand ? mQsMaxExpansionHeight : mQsMinExpansionHeight; ValueAnimator animator = ValueAnimator.ofFloat(mQsExpansionHeight, target); - animator.setDuration(EXPANSION_ANIMATION_LENGTH); - animator.setInterpolator(mExpansionInterpolator); + mFlingAnimationUtils.apply(animator, mQsExpansionHeight, target, vel); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { |