diff options
author | Jorim Jaggi <jjaggi@google.com> | 2014-06-02 14:44:49 +0200 |
---|---|---|
committer | Jorim Jaggi <jjaggi@google.com> | 2014-06-02 15:35:54 +0200 |
commit | 9012958742c7a66b37ba5f2196f9086bb1980e6b (patch) | |
tree | c922ccf645eb12ad6324bc8b1c237fa9e4f2c6da /packages | |
parent | 290600a08d0b7df691d6140b5557d795cd0581de (diff) | |
download | frameworks_base-9012958742c7a66b37ba5f2196f9086bb1980e6b.zip frameworks_base-9012958742c7a66b37ba5f2196f9086bb1980e6b.tar.gz frameworks_base-9012958742c7a66b37ba5f2196f9086bb1980e6b.tar.bz2 |
Implement unlock hint.
Before, users didn't have any clue how to unlock their phone. Now
they have. Also, a tap now dismisses the notification shade in the
unlocked state.
Bug: 14080971
Bug: 15189435
Bug: 15282191
Bug: 15126962
Change-Id: I779344b043b4415809dd98217b7cb9ff6d57fa3e
Diffstat (limited to 'packages')
6 files changed, 190 insertions, 30 deletions
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 7460c73..bfbdcf3 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -318,4 +318,7 @@ <!-- Volume panel z depth --> <dimen name="volume_panel_z">3dp</dimen> + + <!-- Move distance for the hint animations on the lockscreen (unlock, phone, camera)--> + <dimen name="hint_move_distance">75dp</dimen> </resources> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BounceInterpolator.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BounceInterpolator.java new file mode 100644 index 0000000..367d326 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BounceInterpolator.java @@ -0,0 +1,43 @@ +/* + * 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.phone; + +import android.view.animation.Interpolator; + +/** + * An implementation of a bouncer interpolator optimized for unlock hinting. + */ +public class BounceInterpolator implements Interpolator { + + private final static float SCALE_FACTOR = 7.5625f; + + @Override + public float getInterpolation(float t) { + if (t < 4f / 11f) { + return SCALE_FACTOR * t * t; + } else if (t < 8f / 11f) { + float t2 = t - 6f / 11f; + return SCALE_FACTOR * t2 * t2 + 3f / 4f; + } else if (t < 10f / 11f) { + float t2 = t - 9f / 11f; + return SCALE_FACTOR * t2 * t2 + 15f / 16f; + } else { + float t2 = t - 21f / 22f; + return SCALE_FACTOR * t2 * t2 + 63f / 64f; + } + } +} 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 03d164b..dfd5a88 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -51,7 +51,6 @@ public class NotificationPanelView extends PanelView implements private static float EXPANSION_RUBBER_BAND_EXTRA_FACTOR = 0.6f; private KeyguardPageSwipeHelper mPageSwiper; - PhoneStatusBar mStatusBar; private StatusBarHeaderView mHeader; private View mQsContainer; private View mQsPanel; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java index 220b691..4686933 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java @@ -27,10 +27,13 @@ import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.ViewConfiguration; +import android.view.animation.AnimationUtils; +import android.view.animation.Interpolator; import android.widget.FrameLayout; import com.android.systemui.R; import com.android.systemui.statusbar.FlingAnimationUtils; +import com.android.systemui.statusbar.StatusBarState; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -44,13 +47,16 @@ public abstract class PanelView extends FrameLayout { Log.v(TAG, (mViewName != null ? (mViewName + ": ") : "") + String.format(fmt, args)); } + protected PhoneStatusBar mStatusBar; private float mPeekHeight; + private float mHintDistance; private float mInitialOffsetOnTouch; private float mExpandedFraction = 0; private float mExpandedHeight = 0; private boolean mJustPeeked; private boolean mClosing; private boolean mTracking; + private boolean mTouchSlopExceeded; private int mTrackingPointer; protected int mTouchSlop; @@ -66,6 +72,9 @@ public abstract class PanelView extends FrameLayout { private float mInitialTouchY; private float mInitialTouchX; + private Interpolator mLinearOutSlowInInterpolator; + private Interpolator mBounceInterpolator; + protected void onExpandingFinished() { mBar.onExpandingFinished(); } @@ -89,6 +98,9 @@ public abstract class PanelView extends FrameLayout { public PanelView(Context context, AttributeSet attrs) { super(context, attrs); mFlingAnimationUtils = new FlingAnimationUtils(context, 0.6f); + mLinearOutSlowInInterpolator = + AnimationUtils.loadInterpolator(context, android.R.interpolator.fast_out_slow_in); + mBounceInterpolator = new BounceInterpolator(); } protected void loadDimens() { @@ -98,6 +110,7 @@ public abstract class PanelView extends FrameLayout { final ViewConfiguration configuration = ViewConfiguration.get(getContext()); mTouchSlop = configuration.getScaledTouchSlop(); + mHintDistance = res.getDimension(R.dimen.hint_move_distance); } private void trackMovement(MotionEvent event) { @@ -138,6 +151,7 @@ public abstract class PanelView extends FrameLayout { mInitialTouchY = y; mInitialTouchX = x; mInitialOffsetOnTouch = mExpandedHeight; + mTouchSlopExceeded = false; if (mVelocityTracker == null) { initVelocityTracker(); } @@ -170,16 +184,18 @@ public abstract class PanelView extends FrameLayout { case MotionEvent.ACTION_MOVE: float h = y - mInitialTouchY; - if (waitForTouchSlop && !mTracking && Math.abs(h) > mTouchSlop - && Math.abs(h) > Math.abs(x - mInitialTouchX)) { - mInitialOffsetOnTouch = mExpandedHeight; - mInitialTouchX = x; - mInitialTouchY = y; - if (mHeightAnimator != null) { - mHeightAnimator.cancel(); // end any outstanding animations + if (Math.abs(h) > mTouchSlop && Math.abs(h) > Math.abs(x - mInitialTouchX)) { + mTouchSlopExceeded = true; + if (waitForTouchSlop && !mTracking) { + mInitialOffsetOnTouch = mExpandedHeight; + mInitialTouchX = x; + mInitialTouchY = y; + if (mHeightAnimator != null) { + mHeightAnimator.cancel(); // end any outstanding animations + } + onTrackingStarted(); + h = 0; } - onTrackingStarted(); - h = 0; } final float newHeight = h + mInitialOffsetOnTouch; if (newHeight > mPeekHeight) { @@ -200,10 +216,15 @@ public abstract class PanelView extends FrameLayout { case MotionEvent.ACTION_CANCEL: mTrackingPointer = -1; trackMovement(event); - float vel = getCurrentVelocity(); - boolean expand = flingExpands(vel); - onTrackingStopped(expand); - fling(vel, expand); + if (mTracking && mTouchSlopExceeded) { + float vel = getCurrentVelocity(); + boolean expand = flingExpands(vel); + onTrackingStopped(expand); + fling(vel, expand); + } else { + boolean expands = onEmptySpaceClick(); + onTrackingStopped(expands); + } if (mVelocityTracker != null) { mVelocityTracker.recycle(); mVelocityTracker = null; @@ -264,6 +285,7 @@ public abstract class PanelView extends FrameLayout { } mInitialTouchY = y; mInitialTouchX = x; + mTouchSlopExceeded = false; initVelocityTracker(); trackMovement(event); break; @@ -287,6 +309,7 @@ public abstract class PanelView extends FrameLayout { mInitialTouchY = y; mInitialTouchX = x; mTracking = true; + mTouchSlopExceeded = true; onTrackingStarted(); return true; } @@ -344,7 +367,7 @@ public abstract class PanelView extends FrameLayout { mBar.panelExpansionChanged(this, mExpandedFraction); return; } - ValueAnimator animator = ValueAnimator.ofFloat(mExpandedHeight, target); + ValueAnimator animator = createHeightAnimator(target); if (expand) { mFlingAnimationUtils.apply(animator, mExpandedHeight, target, vel, getHeight()); } else { @@ -356,12 +379,6 @@ public abstract class PanelView extends FrameLayout { animator.setDuration((long) (animator.getDuration() / 1.75f)); } } - animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animation) { - setExpandedHeight((Float) animation.getAnimatedValue()); - } - }); animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { @@ -449,9 +466,7 @@ public abstract class PanelView extends FrameLayout { mOverExpansion = overExpansion; } - protected void onHeightUpdated(float expandedHeight) { - requestLayout(); - } + protected abstract void onHeightUpdated(float expandedHeight); /** * This returns the maximum height of the panel. Children should override this if their @@ -526,6 +541,101 @@ public abstract class PanelView extends FrameLayout { } } + protected void startUnlockHintAnimation() { + + // We don't need to hint the user if an animation is already running or the user is changing + // the expansion. + if (mHeightAnimator != null || mTracking) { + return; + } + cancelPeek(); + onExpandingStarted(); + startUnlockHintAnimationPhase1(); + mStatusBar.onUnlockHintStarted(); + } + + /** + * Phase 1: Move everything upwards. + */ + private void startUnlockHintAnimationPhase1() { + float target = Math.max(0, getMaxPanelHeight() - mHintDistance); + ValueAnimator animator = createHeightAnimator(target); + animator.setDuration(250); + animator.setInterpolator(mLinearOutSlowInInterpolator); + animator.addListener(new AnimatorListenerAdapter() { + private boolean mCancelled; + + @Override + public void onAnimationCancel(Animator animation) { + mCancelled = true; + } + + @Override + public void onAnimationEnd(Animator animation) { + if (mCancelled) { + mHeightAnimator = null; + onExpandingFinished(); + mStatusBar.onUnlockHintFinished(); + } else { + startUnlockHintAnimationPhase2(); + } + } + }); + animator.start(); + mHeightAnimator = animator; + } + + /** + * Phase 2: Bounce down. + */ + private void startUnlockHintAnimationPhase2() { + ValueAnimator animator = createHeightAnimator(getMaxPanelHeight()); + animator.setDuration(450); + animator.setInterpolator(mBounceInterpolator); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mHeightAnimator = null; + onExpandingFinished(); + mStatusBar.onUnlockHintFinished(); + } + }); + animator.start(); + mHeightAnimator = animator; + } + + private ValueAnimator createHeightAnimator(float targetHeight) { + ValueAnimator animator = ValueAnimator.ofFloat(mExpandedHeight, targetHeight); + animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + setExpandedHeight((Float) animation.getAnimatedValue()); + } + }); + return animator; + } + + /** + * Gets called when the user performs a click anywhere in the empty area of the panel. + * + * @return whether the panel will be expanded after the action performed by this method + */ + private boolean onEmptySpaceClick() { + switch (mStatusBar.getBarState()) { + case StatusBarState.KEYGUARD: + startUnlockHintAnimation(); + return true; + case StatusBarState.SHADE_LOCKED: + // TODO: Go to Keyguard again. + return true; + case StatusBarState.SHADE: + collapse(); + return false; + default: + return true; + } + } + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println(String.format("[PanelView(%s): expandedHeight=%f maxPanelHeight=%d closing=%s" + " tracking=%s justPeeked=%s peekAnim=%s%s timeAnim=%s%s" diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index f6e6fa8..b1216e6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -2957,15 +2957,17 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } public void onTrackingStarted() { - if (mState == StatusBarState.KEYGUARD) { - mKeyguardIndicationTextView.switchIndication(R.string.keyguard_unlock); - } + } + + public void onUnlockHintStarted() { + mKeyguardIndicationTextView.switchIndication(R.string.keyguard_unlock); + } + + public void onUnlockHintFinished() { + mKeyguardIndicationTextView.switchIndication(mKeyguardHotwordPhrase); } public void onTrackingStopped(boolean expand) { - if (mState == StatusBarState.KEYGUARD) { - mKeyguardIndicationTextView.switchIndication(mKeyguardHotwordPhrase); - } if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) { if (!expand && !mUnlockMethodCache.isMethodInsecure()) { showBouncer(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java index f41ab3a..2edd7d1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java @@ -715,6 +715,9 @@ public class StackStateAnimator { public void animateOverScrollToAmount(float targetAmount, final boolean onTop) { final float startOverScrollAmount = mHostLayout.getCurrentOverScrollAmount(onTop); + if (targetAmount == startOverScrollAmount) { + return; + } cancelOverScrollAnimators(onTop); ValueAnimator overScrollAnimator = ValueAnimator.ofFloat(startOverScrollAmount, targetAmount); |