150a531337e7d6d49b40a1c96636962507ccf6c61Daniel Sandler/* 250a531337e7d6d49b40a1c96636962507ccf6c61Daniel Sandler * Copyright (C) 2012 The Android Open Source Project 350a531337e7d6d49b40a1c96636962507ccf6c61Daniel Sandler * 450a531337e7d6d49b40a1c96636962507ccf6c61Daniel Sandler * Licensed under the Apache License, Version 2.0 (the "License"); 550a531337e7d6d49b40a1c96636962507ccf6c61Daniel Sandler * you may not use this file except in compliance with the License. 650a531337e7d6d49b40a1c96636962507ccf6c61Daniel Sandler * You may obtain a copy of the License at 750a531337e7d6d49b40a1c96636962507ccf6c61Daniel Sandler * 850a531337e7d6d49b40a1c96636962507ccf6c61Daniel Sandler * http://www.apache.org/licenses/LICENSE-2.0 950a531337e7d6d49b40a1c96636962507ccf6c61Daniel Sandler * 1050a531337e7d6d49b40a1c96636962507ccf6c61Daniel Sandler * Unless required by applicable law or agreed to in writing, software 1150a531337e7d6d49b40a1c96636962507ccf6c61Daniel Sandler * distributed under the License is distributed on an "AS IS" BASIS, 1250a531337e7d6d49b40a1c96636962507ccf6c61Daniel Sandler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1350a531337e7d6d49b40a1c96636962507ccf6c61Daniel Sandler * See the License for the specific language governing permissions and 1450a531337e7d6d49b40a1c96636962507ccf6c61Daniel Sandler * limitations under the License. 1550a531337e7d6d49b40a1c96636962507ccf6c61Daniel Sandler */ 1650a531337e7d6d49b40a1c96636962507ccf6c61Daniel Sandler 1708d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandlerpackage com.android.systemui.statusbar.phone; 1808d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 191d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggiimport android.animation.Animator; 201d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggiimport android.animation.AnimatorListenerAdapter; 210c1b75c17b79979e0f210b5bf03226d1091a4c21Daniel Sandlerimport android.animation.ObjectAnimator; 221d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggiimport android.animation.ValueAnimator; 2308d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandlerimport android.content.Context; 24b84a1074b34f64174d9451234fa7c684f8283b6cSelim Cinekimport android.content.res.Configuration; 2508d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandlerimport android.content.res.Resources; 2608d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandlerimport android.util.AttributeSet; 27cd686b5b6d4166b510df8e32138479a9559bc117John Spurlockimport android.util.Log; 28de750b4499763f0470c5291a518fad82052760ceJun Mukaiimport android.view.InputDevice; 2908d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandlerimport android.view.MotionEvent; 30b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinekimport android.view.ViewConfiguration; 310a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggiimport android.view.ViewTreeObserver; 329012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggiimport android.view.animation.Interpolator; 3308d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandlerimport android.widget.FrameLayout; 3408d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 35b018399a3a2762e95126acbe14397eca15bad772Christoph Studerimport com.android.systemui.EventLogConstants; 36b018399a3a2762e95126acbe14397eca15bad772Christoph Studerimport com.android.systemui.EventLogTags; 37c0d7058b14c24cd07912f5629c26b39b7b4673d5Winsonimport com.android.systemui.Interpolators; 3808d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandlerimport com.android.systemui.R; 390e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowskiimport com.android.systemui.classifier.FalsingManager; 40813552cc27cbeac366166cdda82fd813c8458bbfJohn Spurlockimport com.android.systemui.doze.DozeLog; 411d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggiimport com.android.systemui.statusbar.FlingAnimationUtils; 429012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggiimport com.android.systemui.statusbar.StatusBarState; 43b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinekimport com.android.systemui.statusbar.policy.HeadsUpManager; 4408d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 45de84f0e77ea2bf713d15c290264059a413c2486aJohn Spurlockimport java.io.FileDescriptor; 46de84f0e77ea2bf713d15c290264059a413c2486aJohn Spurlockimport java.io.PrintWriter; 47de84f0e77ea2bf713d15c290264059a413c2486aJohn Spurlock 484c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinekpublic abstract class PanelView extends FrameLayout { 49198a0306e5b0ef6b02d61e299a4b4ab4c1c2cdc8Daniel Sandler public static final boolean DEBUG = PanelBar.DEBUG; 5008d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler public static final String TAG = PanelView.class.getSimpleName(); 51173f2d0fad8dc889beefff67be96ec865465d1e0Selim Cinek 529764218ff979f735aee2f1189e3547d5f3b02f83John Spurlock private final void logf(String fmt, Object... args) { 53cd686b5b6d4166b510df8e32138479a9559bc117John Spurlock Log.v(TAG, (mViewName != null ? (mViewName + ": ") : "") + String.format(fmt, args)); 5408d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 5508d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 569012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi protected PhoneStatusBar mStatusBar; 57684a442b812a5e95d813700ffa2fd17ca72048a7Selim Cinek protected HeadsUpManager mHeadsUpManager; 58684a442b812a5e95d813700ffa2fd17ca72048a7Selim Cinek 590c1b75c17b79979e0f210b5bf03226d1091a4c21Daniel Sandler private float mPeekHeight; 609012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi private float mHintDistance; 61b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek private float mInitialOffsetOnTouch; 6279d79c455beecf7a70460575ab21d9bf49767e2cSelim Cinek private boolean mCollapsedAndHeadsUpOnDown; 6308d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler private float mExpandedFraction = 0; 641408eb5a58d669933c701e347fd3498ceab70f3cSelim Cinek protected float mExpandedHeight = 0; 6531094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek private boolean mPanelClosedOnDown; 6631094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek private boolean mHasLayoutedSinceDown; 6731094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek private float mUpdateFlingVelocity; 6831094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek private boolean mUpdateFlingOnLayout; 69b7a3303f807ee01bbe405f4153a2285e55c0b6e3Jorim Jaggi private boolean mPeekTouching; 700c1b75c17b79979e0f210b5bf03226d1091a4c21Daniel Sandler private boolean mJustPeeked; 715050813f15a1d39d49cb8eca5a3aa6df43c4d450Daniel Sandler private boolean mClosing; 728dd95e03f8555c278217bac7e4faef865b1850a7Jorim Jaggi protected boolean mTracking; 739012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi private boolean mTouchSlopExceeded; 7448fa91a818e321208e90d6af234c1d4bed5a945dJohn Spurlock private int mTrackingPointer; 75d7daab7b9e33cd56f2692b9ebea87ef21290c1eaJorim Jaggi protected int mTouchSlop; 76b3f0a2ff000ca2481f95ee8f7d7b487e33b87ecaJorim Jaggi protected boolean mHintAnimationRunning; 7747c85a3525dcd0bbd3168632830e8ab491d18462Jorim Jaggi private boolean mOverExpandedBeforeFling; 7819c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek private boolean mTouchAboveFalsingThreshold; 7919c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek private int mUnlockFalsingThreshold; 80ab1dc954b2b97b59f868c96921f2daabc3336034Selim Cinek private boolean mTouchStartedInEmptyArea; 81547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek private boolean mMotionAborted; 829db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek private boolean mUpwardsWhenTresholdReached; 83173f2d0fad8dc889beefff67be96ec865465d1e0Selim Cinek private boolean mAnimatingOnDown; 8408d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 851d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi private ValueAnimator mHeightAnimator; 860c1b75c17b79979e0f210b5bf03226d1091a4c21Daniel Sandler private ObjectAnimator mPeekAnimator; 87b7b61ddaef4f2a2ebc79e832fb909fd4dcac8ba5Jorim Jaggi private VelocityTrackerInterface mVelocityTracker; 881d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi private FlingAnimationUtils mFlingAnimationUtils; 890e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski private FalsingManager mFalsingManager; 9008d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 910a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi /** 920a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi * Whether an instant expand request is currently pending and we are just waiting for layout. 930a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi */ 940a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi private boolean mInstantExpanding; 956626f54e658e3da44fab8a5cd6d9d3d4852e2cd1Jorim Jaggi private boolean mAnimateAfterExpanding; 960a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi 9708d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler PanelBar mBar; 9808d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 995050813f15a1d39d49cb8eca5a3aa6df43c4d450Daniel Sandler private String mViewName; 100d7daab7b9e33cd56f2692b9ebea87ef21290c1eaJorim Jaggi private float mInitialTouchY; 101d7daab7b9e33cd56f2692b9ebea87ef21290c1eaJorim Jaggi private float mInitialTouchX; 102d41083ad06f63e335a1d1a1d5050ed3646f4fd35Jorim Jaggi private boolean mTouchDisabled; 10308d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 1049012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi private Interpolator mBounceInterpolator; 105f99d0007646781b99a63bc0d2103a45f0f72e724Selim Cinek protected KeyguardBottomAreaView mKeyguardBottomArea; 1069012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi 107b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi private boolean mPeekPending; 108b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi private boolean mCollapseAfterPeek; 109f3b3bee12994a24b60bd447dede9e8791151fcc9Jorim Jaggi 110f3b3bee12994a24b60bd447dede9e8791151fcc9Jorim Jaggi /** 111f3b3bee12994a24b60bd447dede9e8791151fcc9Jorim Jaggi * Speed-up factor to be used when {@link #mFlingCollapseRunnable} runs the next time. 112f3b3bee12994a24b60bd447dede9e8791151fcc9Jorim Jaggi */ 113f3b3bee12994a24b60bd447dede9e8791151fcc9Jorim Jaggi private float mNextCollapseSpeedUpFactor = 1.0f; 114f3b3bee12994a24b60bd447dede9e8791151fcc9Jorim Jaggi 1151d071ce9b1810fbcf231fd17c4cb5621e68ff419Jorim Jaggi protected boolean mExpanding; 116b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi private boolean mGestureWaitForTouchSlop; 1179db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek private boolean mIgnoreXTouchSlop; 118b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi private Runnable mPeekRunnable = new Runnable() { 119b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi @Override 120b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi public void run() { 121b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi mPeekPending = false; 122b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi runPeekAnimation(); 123b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi } 124b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi }; 125b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi 1261685e634fb0b14033bd436af8d7174436699ffecSelim Cinek protected void onExpandingFinished() { 1272fbad7b6a724cf0a5b98b66fe639d58f5ab10af3Jorim Jaggi mBar.onExpandingFinished(); 1281685e634fb0b14033bd436af8d7174436699ffecSelim Cinek } 1291685e634fb0b14033bd436af8d7174436699ffecSelim Cinek 1301685e634fb0b14033bd436af8d7174436699ffecSelim Cinek protected void onExpandingStarted() { 1311685e634fb0b14033bd436af8d7174436699ffecSelim Cinek } 1321685e634fb0b14033bd436af8d7174436699ffecSelim Cinek 133b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi private void notifyExpandingStarted() { 134b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi if (!mExpanding) { 135b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi mExpanding = true; 136b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi onExpandingStarted(); 137b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi } 138b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi } 139b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi 1401d071ce9b1810fbcf231fd17c4cb5621e68ff419Jorim Jaggi protected final void notifyExpandingFinished() { 141b0e4f9e97e272783f08b2245219239aaa667073dSelim Cinek endClosing(); 142b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi if (mExpanding) { 143b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi mExpanding = false; 144b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi onExpandingFinished(); 145b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi } 146b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi } 147b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi 148b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi private void schedulePeek() { 149b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi mPeekPending = true; 150b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi long timeout = ViewConfiguration.getTapTimeout(); 151b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi postOnAnimationDelayed(mPeekRunnable, timeout); 152b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi notifyBarPanelExpansionChanged(); 153b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi } 154b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi 1550c1b75c17b79979e0f210b5bf03226d1091a4c21Daniel Sandler private void runPeekAnimation() { 1562580a976ec93a01ed00fae51364ad872bc591d95Jorim Jaggi mPeekHeight = getPeekHeight(); 1579764218ff979f735aee2f1189e3547d5f3b02f83John Spurlock if (DEBUG) logf("peek to height=%.1f", mPeekHeight); 1581d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi if (mHeightAnimator != null) { 1590c1b75c17b79979e0f210b5bf03226d1091a4c21Daniel Sandler return; 1600c1b75c17b79979e0f210b5bf03226d1091a4c21Daniel Sandler } 161b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi mPeekAnimator = ObjectAnimator.ofFloat(this, "expandedHeight", mPeekHeight) 162b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi .setDuration(250); 163c18010f6720f606003cde3cd376ddacaca30f6e5Selim Cinek mPeekAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN); 164b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi mPeekAnimator.addListener(new AnimatorListenerAdapter() { 165b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi private boolean mCancelled; 166b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi 167b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi @Override 168b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi public void onAnimationCancel(Animator animation) { 169b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi mCancelled = true; 170b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi } 171b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi 172b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi @Override 173b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi public void onAnimationEnd(Animator animation) { 174b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi mPeekAnimator = null; 175b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi if (mCollapseAfterPeek && !mCancelled) { 176a0f5c76ffdc728c9f291addd3f4a7bc2d1817733Selim Cinek postOnAnimation(mPostCollapseRunnable); 177b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi } 178b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi mCollapseAfterPeek = false; 179b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi } 180b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi }); 181b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi notifyExpandingStarted(); 1820c1b75c17b79979e0f210b5bf03226d1091a4c21Daniel Sandler mPeekAnimator.start(); 183b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi mJustPeeked = true; 1840c1b75c17b79979e0f210b5bf03226d1091a4c21Daniel Sandler } 1850c1b75c17b79979e0f210b5bf03226d1091a4c21Daniel Sandler 18608d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler public PanelView(Context context, AttributeSet attrs) { 18708d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler super(context, attrs); 1881d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi mFlingAnimationUtils = new FlingAnimationUtils(context, 0.6f); 1899012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi mBounceInterpolator = new BounceInterpolator(); 1900e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski mFalsingManager = FalsingManager.getInstance(context); 19108d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 19208d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 193069cd03740312159faf24a01910ff1daeae93131Jorim Jaggi protected void loadDimens() { 19408d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler final Resources res = getContext().getResources(); 195b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek final ViewConfiguration configuration = ViewConfiguration.get(getContext()); 196b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek mTouchSlop = configuration.getScaledTouchSlop(); 1979012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi mHintDistance = res.getDimension(R.dimen.hint_move_distance); 19819c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek mUnlockFalsingThreshold = res.getDimensionPixelSize(R.dimen.unlock_falsing_threshold); 19908d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 20008d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 20108d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler private void trackMovement(MotionEvent event) { 20208d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler // Add movement to velocity tracker using raw screen X and Y coordinates instead 20308d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler // of window coordinates because the window frame may be moving at the same time. 20408d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler float deltaX = event.getRawX() - event.getX(); 20508d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler float deltaY = event.getRawY() - event.getY(); 20608d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler event.offsetLocation(deltaX, deltaY); 207b17a726f2fb1066060b5646d35233d26222e8721Daniel Sandler if (mVelocityTracker != null) mVelocityTracker.addMovement(event); 20808d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler event.offsetLocation(-deltaX, -deltaY); 20908d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 21008d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 211d41083ad06f63e335a1d1a1d5050ed3646f4fd35Jorim Jaggi public void setTouchDisabled(boolean disabled) { 212d41083ad06f63e335a1d1a1d5050ed3646f4fd35Jorim Jaggi mTouchDisabled = disabled; 2133127daf036337e047746f4b6bca56cc5ae18259cSelim Cinek if (mTouchDisabled && mTracking) { 2143127daf036337e047746f4b6bca56cc5ae18259cSelim Cinek onTrackingStopped(true /* expanded */); 2153127daf036337e047746f4b6bca56cc5ae18259cSelim Cinek } 216d41083ad06f63e335a1d1a1d5050ed3646f4fd35Jorim Jaggi } 217d41083ad06f63e335a1d1a1d5050ed3646f4fd35Jorim Jaggi 218bf526d14f3252b8a5c123291e4cd8b1c51346560Daniel Sandler @Override 219bf526d14f3252b8a5c123291e4cd8b1c51346560Daniel Sandler public boolean onTouchEvent(MotionEvent event) { 220547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek if (mInstantExpanding || mTouchDisabled 221547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek || (mMotionAborted && event.getActionMasked() != MotionEvent.ACTION_DOWN)) { 2220a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi return false; 2230a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi } 224b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek 225cf9933cf39e0f924dc25ba918617ed66572fd9e9Jun Mukai // On expanding, single mouse click expands the panel instead of dragging. 226c99243aff8f039734fcc9af93f6854c3838796cfJun Mukai if (isFullyCollapsed() && event.isFromSource(InputDevice.SOURCE_MOUSE)) { 227cf9933cf39e0f924dc25ba918617ed66572fd9e9Jun Mukai if (event.getAction() == MotionEvent.ACTION_UP) { 228cf9933cf39e0f924dc25ba918617ed66572fd9e9Jun Mukai expand(true); 229cf9933cf39e0f924dc25ba918617ed66572fd9e9Jun Mukai } 230cf9933cf39e0f924dc25ba918617ed66572fd9e9Jun Mukai return true; 231cf9933cf39e0f924dc25ba918617ed66572fd9e9Jun Mukai } 232cf9933cf39e0f924dc25ba918617ed66572fd9e9Jun Mukai 233b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek /* 234b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek * We capture touch events here and update the expand height here in case according to 235b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek * the users fingers. This also handles multi-touch. 236b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek * 2375d53df4aede972cfa23d9f2a3f484fb5ee3087dcChris Wren * If the user just clicks shortly, we show a quick peek of the shade. 238b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek * 239b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek * Flinging is also enabled in order to open or close the shade. 240b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek */ 241b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek 242b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek int pointerIndex = event.findPointerIndex(mTrackingPointer); 243b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek if (pointerIndex < 0) { 244b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek pointerIndex = 0; 245b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek mTrackingPointer = event.getPointerId(pointerIndex); 246b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek } 247a6310293c5a861cdb54f2c894e90a8d9da87f8d7Jorim Jaggi final float x = event.getX(pointerIndex); 248547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek final float y = event.getY(pointerIndex); 249b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek 250b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { 251684a442b812a5e95d813700ffa2fd17ca72048a7Selim Cinek mGestureWaitForTouchSlop = isFullyCollapsed() || hasConflictingGestures(); 252684a442b812a5e95d813700ffa2fd17ca72048a7Selim Cinek mIgnoreXTouchSlop = isFullyCollapsed() || shouldGestureIgnoreXTouchSlop(x, y); 253b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi } 2544c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek 255b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek switch (event.getActionMasked()) { 256b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek case MotionEvent.ACTION_DOWN: 257b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek startExpandMotion(x, y, false /* startTracking */, mExpandedHeight); 2583857ac4b3f24e13bac255d162249dd8b2ccb63acJorim Jaggi mJustPeeked = false; 259684a442b812a5e95d813700ffa2fd17ca72048a7Selim Cinek mPanelClosedOnDown = isFullyCollapsed(); 26031094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek mHasLayoutedSinceDown = false; 26131094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek mUpdateFlingOnLayout = false; 262547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek mMotionAborted = false; 263b7a3303f807ee01bbe405f4153a2285e55c0b6e3Jorim Jaggi mPeekTouching = mPanelClosedOnDown; 26419c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek mTouchAboveFalsingThreshold = false; 26579d79c455beecf7a70460575ab21d9bf49767e2cSelim Cinek mCollapsedAndHeadsUpOnDown = isFullyCollapsed() 26679d79c455beecf7a70460575ab21d9bf49767e2cSelim Cinek && mHeadsUpManager.hasPinnedHeadsUp(); 267b7b61ddaef4f2a2ebc79e832fb909fd4dcac8ba5Jorim Jaggi if (mVelocityTracker == null) { 268b7b61ddaef4f2a2ebc79e832fb909fd4dcac8ba5Jorim Jaggi initVelocityTracker(); 269b7b61ddaef4f2a2ebc79e832fb909fd4dcac8ba5Jorim Jaggi } 270b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek trackMovement(event); 2719db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek if (!mGestureWaitForTouchSlop || (mHeightAnimator != null && !mHintAnimationRunning) || 272b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi mPeekPending || mPeekAnimator != null) { 273dbbcfbe8aea1944fc0b0ecbf531034bcd5b5770aSelim Cinek cancelHeightAnimator(); 274b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi cancelPeek(); 275b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi mTouchSlopExceeded = (mHeightAnimator != null && !mHintAnimationRunning) 276b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi || mPeekPending || mPeekAnimator != null; 2774c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek onTrackingStarted(); 2781d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi } 27979d79c455beecf7a70460575ab21d9bf49767e2cSelim Cinek if (isFullyCollapsed() && !mHeadsUpManager.hasPinnedHeadsUp()) { 280b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi schedulePeek(); 281b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek } 282b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek break; 283b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek 284b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek case MotionEvent.ACTION_POINTER_UP: 285b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek final int upPointer = event.getPointerId(event.getActionIndex()); 286b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek if (mTrackingPointer == upPointer) { 287b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek // gesture is ongoing, find a new pointer to track 288b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek final int newIndex = event.getPointerId(0) != upPointer ? 0 : 1; 289b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek final float newY = event.getY(newIndex); 290a6310293c5a861cdb54f2c894e90a8d9da87f8d7Jorim Jaggi final float newX = event.getX(newIndex); 291b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek mTrackingPointer = event.getPointerId(newIndex); 292b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek startExpandMotion(newX, newY, true /* startTracking */, mExpandedHeight); 293b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek } 294b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek break; 295547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek case MotionEvent.ACTION_POINTER_DOWN: 296547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek if (mStatusBar.getBarState() == StatusBarState.KEYGUARD) { 297547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek mMotionAborted = true; 298547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek endMotionEvent(event, x, y, true /* forceCancel */); 299547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek return false; 300547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek } 301547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek break; 302b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek case MotionEvent.ACTION_MOVE: 3034c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek float h = y - mInitialTouchY; 304b7240136b748e548069c7fe2bd77a7ed4148728eJorim Jaggi 305b7240136b748e548069c7fe2bd77a7ed4148728eJorim Jaggi // If the panel was collapsed when touching, we only need to check for the 306b7240136b748e548069c7fe2bd77a7ed4148728eJorim Jaggi // y-component of the gesture, as we have no conflicting horizontal gesture. 307b7240136b748e548069c7fe2bd77a7ed4148728eJorim Jaggi if (Math.abs(h) > mTouchSlop 308b7240136b748e548069c7fe2bd77a7ed4148728eJorim Jaggi && (Math.abs(h) > Math.abs(x - mInitialTouchX) 3099db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek || mIgnoreXTouchSlop)) { 3109012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi mTouchSlopExceeded = true; 31179d79c455beecf7a70460575ab21d9bf49767e2cSelim Cinek if (mGestureWaitForTouchSlop && !mTracking && !mCollapsedAndHeadsUpOnDown) { 3120b1528aac46007f94f0e073143708240b0c7c144Jorim Jaggi if (!mJustPeeked && mInitialOffsetOnTouch != 0f) { 313b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek startExpandMotion(x, y, false /* startTracking */, mExpandedHeight); 314b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi h = 0; 315b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi } 316dbbcfbe8aea1944fc0b0ecbf531034bcd5b5770aSelim Cinek cancelHeightAnimator(); 317b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi removeCallbacks(mPeekRunnable); 318b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi mPeekPending = false; 3199012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi onTrackingStarted(); 3204c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek } 3214c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek } 32293439da0ed9213bc54291b3fce4e04dd3a7f9f3aJorim Jaggi final float newHeight = Math.max(0, h + mInitialOffsetOnTouch); 3234c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek if (newHeight > mPeekHeight) { 324b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi if (mPeekAnimator != null) { 325b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek mPeekAnimator.cancel(); 326b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek } 327b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek mJustPeeked = false; 328b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek } 32929ed3c92ef8a28975606f6213477ce5ee2c99ba9Selim Cinek if (-h >= getFalsingThreshold()) { 33019c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek mTouchAboveFalsingThreshold = true; 3319db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek mUpwardsWhenTresholdReached = isDirectionUpwards(x, y); 33219c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek } 3339db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek if (!mJustPeeked && (!mGestureWaitForTouchSlop || mTracking) && !isTrackingBlocked()) { 334cc693247dceef098490a4b01f2c0793ba5f948a4Jorim Jaggi setExpandedHeightInternal(newHeight); 335b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek } 336b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek 337b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek trackMovement(event); 338b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek break; 339b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek 340b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek case MotionEvent.ACTION_UP: 341b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek case MotionEvent.ACTION_CANCEL: 342b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek trackMovement(event); 343547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek endMotionEvent(event, x, y, false /* forceCancel */); 344547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek break; 345547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek } 3469db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek return !mGestureWaitForTouchSlop || mTracking; 3479db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek } 3489db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek 3499db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek /** 3509db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek * @return whether the swiping direction is upwards and above a 45 degree angle compared to the 3519db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek * horizontal direction 3529db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek */ 3539db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek private boolean isDirectionUpwards(float x, float y) { 3549db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek float xDiff = x - mInitialTouchX; 3559db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek float yDiff = y - mInitialTouchY; 3569db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek if (yDiff >= 0) { 3579db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek return false; 3589db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek } 3599db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek return Math.abs(yDiff) >= Math.abs(xDiff); 360547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek } 361547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek 362b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek protected void startExpandMotion(float newX, float newY, boolean startTracking, 363b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek float expandedHeight) { 364b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mInitialOffsetOnTouch = expandedHeight; 365b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mInitialTouchY = newY; 366b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mInitialTouchX = newX; 367b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek if (startTracking) { 368b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mTouchSlopExceeded = true; 369def35a86530200958384191d43d321dbcda16e2aSelim Cinek setExpandedHeight(mInitialOffsetOnTouch); 370b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek onTrackingStarted(); 371b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 372b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 373b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 374547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek private void endMotionEvent(MotionEvent event, float x, float y, boolean forceCancel) { 375547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek mTrackingPointer = -1; 376547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek if ((mTracking && mTouchSlopExceeded) 377547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek || Math.abs(x - mInitialTouchX) > mTouchSlop 378547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek || Math.abs(y - mInitialTouchY) > mTouchSlop 379547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek || event.getActionMasked() == MotionEvent.ACTION_CANCEL 380547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek || forceCancel) { 381547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek float vel = 0f; 382547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek float vectorVel = 0f; 383547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek if (mVelocityTracker != null) { 384547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek mVelocityTracker.computeCurrentVelocity(1000); 385547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek vel = mVelocityTracker.getYVelocity(); 386547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek vectorVel = (float) Math.hypot( 387547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek mVelocityTracker.getXVelocity(), mVelocityTracker.getYVelocity()); 388547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek } 3899db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek boolean expand = flingExpands(vel, vectorVel, x, y) 390547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek || event.getActionMasked() == MotionEvent.ACTION_CANCEL 391547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek || forceCancel; 392547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek DozeLog.traceFling(expand, mTouchAboveFalsingThreshold, 393547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek mStatusBar.isFalsingThresholdNeeded(), 39450ff3afb01f2ac4a93dba418a71d54ad8adeba9dJorim Jaggi mStatusBar.isWakeUpComingFromTouch()); 395b018399a3a2762e95126acbe14397eca15bad772Christoph Studer // Log collapse gesture if on lock screen. 396b018399a3a2762e95126acbe14397eca15bad772Christoph Studer if (!expand && mStatusBar.getBarState() == StatusBarState.KEYGUARD) { 397b018399a3a2762e95126acbe14397eca15bad772Christoph Studer float displayDensity = mStatusBar.getDisplayDensity(); 398b018399a3a2762e95126acbe14397eca15bad772Christoph Studer int heightDp = (int) Math.abs((y - mInitialTouchY) / displayDensity); 399b018399a3a2762e95126acbe14397eca15bad772Christoph Studer int velocityDp = (int) Math.abs(vel / displayDensity); 400b018399a3a2762e95126acbe14397eca15bad772Christoph Studer EventLogTags.writeSysuiLockscreenGesture( 401b018399a3a2762e95126acbe14397eca15bad772Christoph Studer EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_SWIPE_UP_UNLOCK, 402b018399a3a2762e95126acbe14397eca15bad772Christoph Studer heightDp, velocityDp); 403b018399a3a2762e95126acbe14397eca15bad772Christoph Studer } 4049db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek fling(vel, expand, isFalseTouch(x, y)); 405eb8f11a8657a1509d6c00b3c6f34547f803bbe67Jorim Jaggi onTrackingStopped(expand); 406547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek mUpdateFlingOnLayout = expand && mPanelClosedOnDown && !mHasLayoutedSinceDown; 407547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek if (mUpdateFlingOnLayout) { 408547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek mUpdateFlingVelocity = vel; 409547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek } 410547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek } else { 411547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek boolean expands = onEmptySpaceClick(mInitialTouchX); 412547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek onTrackingStopped(expands); 413547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek } 414dc96d6310c6e13077a563b80f190550d87e95ff9Jorim Jaggi 415547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek if (mVelocityTracker != null) { 416547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek mVelocityTracker.recycle(); 417547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek mVelocityTracker = null; 418b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek } 419547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek mPeekTouching = false; 420b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek } 421b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek 42229ed3c92ef8a28975606f6213477ce5ee2c99ba9Selim Cinek private int getFalsingThreshold() { 42350ff3afb01f2ac4a93dba418a71d54ad8adeba9dJorim Jaggi float factor = mStatusBar.isWakeUpComingFromTouch() ? 1.5f : 1.0f; 42429ed3c92ef8a28975606f6213477ce5ee2c99ba9Selim Cinek return (int) (mUnlockFalsingThreshold * factor); 42529ed3c92ef8a28975606f6213477ce5ee2c99ba9Selim Cinek } 42629ed3c92ef8a28975606f6213477ce5ee2c99ba9Selim Cinek 4274c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek protected abstract boolean hasConflictingGestures(); 4284c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek 4299db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek protected abstract boolean shouldGestureIgnoreXTouchSlop(float x, float y); 4309db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek 4312fbad7b6a724cf0a5b98b66fe639d58f5ab10af3Jorim Jaggi protected void onTrackingStopped(boolean expand) { 4324c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek mTracking = false; 4339f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen mBar.onTrackingStopped(expand); 434eb8f11a8657a1509d6c00b3c6f34547f803bbe67Jorim Jaggi notifyBarPanelExpansionChanged(); 4351685e634fb0b14033bd436af8d7174436699ffecSelim Cinek } 4361685e634fb0b14033bd436af8d7174436699ffecSelim Cinek 4371685e634fb0b14033bd436af8d7174436699ffecSelim Cinek protected void onTrackingStarted() { 438dbbcfbe8aea1944fc0b0ecbf531034bcd5b5770aSelim Cinek endClosing(); 4394c6969a512cd70831249ec1d07691f16fe5465f5Selim Cinek mTracking = true; 440b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi mCollapseAfterPeek = false; 4419f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen mBar.onTrackingStarted(); 442b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi notifyExpandingStarted(); 443eb8f11a8657a1509d6c00b3c6f34547f803bbe67Jorim Jaggi notifyBarPanelExpansionChanged(); 4441685e634fb0b14033bd436af8d7174436699ffecSelim Cinek } 4451685e634fb0b14033bd436af8d7174436699ffecSelim Cinek 446b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek @Override 447b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek public boolean onInterceptTouchEvent(MotionEvent event) { 448547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek if (mInstantExpanding 449547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek || (mMotionAborted && event.getActionMasked() != MotionEvent.ACTION_DOWN)) { 4500a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi return false; 4510a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi } 452b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek 453b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek /* 4545d53df4aede972cfa23d9f2a3f484fb5ee3087dcChris Wren * If the user drags anywhere inside the panel we intercept it if the movement is 455b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek * upwards. This allows closing the shade from anywhere inside the panel. 456b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek * 457b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek * We only do this if the current content is scrolled to the bottom, 458b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek * i.e isScrolledToBottom() is true and therefore there is no conflicting scrolling gesture 459b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek * possible. 460b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek */ 461b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek int pointerIndex = event.findPointerIndex(mTrackingPointer); 462b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek if (pointerIndex < 0) { 463b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek pointerIndex = 0; 464b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek mTrackingPointer = event.getPointerId(pointerIndex); 465b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek } 466a6310293c5a861cdb54f2c894e90a8d9da87f8d7Jorim Jaggi final float x = event.getX(pointerIndex); 467b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek final float y = event.getY(pointerIndex); 468b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek boolean scrolledToBottom = isScrolledToBottom(); 469b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek 470b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek switch (event.getActionMasked()) { 471b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek case MotionEvent.ACTION_DOWN: 472b690f0d5023fcf144f2701058d5a6f88d66cc97aJorim Jaggi mStatusBar.userActivity(); 473173f2d0fad8dc889beefff67be96ec865465d1e0Selim Cinek mAnimatingOnDown = mHeightAnimator != null; 474173f2d0fad8dc889beefff67be96ec865465d1e0Selim Cinek if (mAnimatingOnDown && mClosing && !mHintAnimationRunning || mPeekPending || mPeekAnimator != null) { 475dbbcfbe8aea1944fc0b0ecbf531034bcd5b5770aSelim Cinek cancelHeightAnimator(); 476b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi cancelPeek(); 477b3f0a2ff000ca2481f95ee8f7d7b487e33b87ecaJorim Jaggi mTouchSlopExceeded = true; 478172e914178181cf1c5999722fc0817e8ac2097f1Selim Cinek return true; 479172e914178181cf1c5999722fc0817e8ac2097f1Selim Cinek } 480b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek mInitialTouchY = y; 481a6310293c5a861cdb54f2c894e90a8d9da87f8d7Jorim Jaggi mInitialTouchX = x; 482ab1dc954b2b97b59f868c96921f2daabc3336034Selim Cinek mTouchStartedInEmptyArea = !isInContentBounds(x, y); 4839012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi mTouchSlopExceeded = false; 4843857ac4b3f24e13bac255d162249dd8b2ccb63acJorim Jaggi mJustPeeked = false; 485547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek mMotionAborted = false; 486684a442b812a5e95d813700ffa2fd17ca72048a7Selim Cinek mPanelClosedOnDown = isFullyCollapsed(); 48779d79c455beecf7a70460575ab21d9bf49767e2cSelim Cinek mCollapsedAndHeadsUpOnDown = false; 48831094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek mHasLayoutedSinceDown = false; 48931094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek mUpdateFlingOnLayout = false; 49019c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek mTouchAboveFalsingThreshold = false; 491b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek initVelocityTracker(); 492b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek trackMovement(event); 493b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek break; 494b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek case MotionEvent.ACTION_POINTER_UP: 495b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek final int upPointer = event.getPointerId(event.getActionIndex()); 496b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek if (mTrackingPointer == upPointer) { 497b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek // gesture is ongoing, find a new pointer to track 498b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek final int newIndex = event.getPointerId(0) != upPointer ? 0 : 1; 499b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek mTrackingPointer = event.getPointerId(newIndex); 500a6310293c5a861cdb54f2c894e90a8d9da87f8d7Jorim Jaggi mInitialTouchX = event.getX(newIndex); 501a6310293c5a861cdb54f2c894e90a8d9da87f8d7Jorim Jaggi mInitialTouchY = event.getY(newIndex); 502b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek } 503b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek break; 504547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek case MotionEvent.ACTION_POINTER_DOWN: 505547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek if (mStatusBar.getBarState() == StatusBarState.KEYGUARD) { 506547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek mMotionAborted = true; 507547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek if (mVelocityTracker != null) { 508547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek mVelocityTracker.recycle(); 509547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek mVelocityTracker = null; 510547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek } 511547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek } 512547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek break; 513b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek case MotionEvent.ACTION_MOVE: 514b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek final float h = y - mInitialTouchY; 515b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek trackMovement(event); 516173f2d0fad8dc889beefff67be96ec865465d1e0Selim Cinek if (scrolledToBottom || mTouchStartedInEmptyArea || mAnimatingOnDown) { 517173f2d0fad8dc889beefff67be96ec865465d1e0Selim Cinek float hAbs = Math.abs(h); 518173f2d0fad8dc889beefff67be96ec865465d1e0Selim Cinek if ((h < -mTouchSlop || (mAnimatingOnDown && hAbs > mTouchSlop)) 519173f2d0fad8dc889beefff67be96ec865465d1e0Selim Cinek && hAbs > Math.abs(x - mInitialTouchX)) { 520dbbcfbe8aea1944fc0b0ecbf531034bcd5b5770aSelim Cinek cancelHeightAnimator(); 521b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek startExpandMotion(x, y, true /* startTracking */, mExpandedHeight); 522b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek return true; 523b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek } 524b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek } 525b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek break; 52631094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek case MotionEvent.ACTION_CANCEL: 52731094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek case MotionEvent.ACTION_UP: 528547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek if (mVelocityTracker != null) { 529547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek mVelocityTracker.recycle(); 530547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek mVelocityTracker = null; 531547a06b50fa97cd079851f80d0d5aa5297cbb040Selim Cinek } 53231094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek break; 533b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek } 534b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek return false; 535b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek } 536b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek 537ab1dc954b2b97b59f868c96921f2daabc3336034Selim Cinek /** 538ab1dc954b2b97b59f868c96921f2daabc3336034Selim Cinek * @return Whether a pair of coordinates are inside the visible view content bounds. 539ab1dc954b2b97b59f868c96921f2daabc3336034Selim Cinek */ 540ab1dc954b2b97b59f868c96921f2daabc3336034Selim Cinek protected abstract boolean isInContentBounds(float x, float y); 541ab1dc954b2b97b59f868c96921f2daabc3336034Selim Cinek 542831941fdd9a800e2838ef60193134763867a333eSelim Cinek protected void cancelHeightAnimator() { 543dbbcfbe8aea1944fc0b0ecbf531034bcd5b5770aSelim Cinek if (mHeightAnimator != null) { 544dbbcfbe8aea1944fc0b0ecbf531034bcd5b5770aSelim Cinek mHeightAnimator.cancel(); 545dbbcfbe8aea1944fc0b0ecbf531034bcd5b5770aSelim Cinek } 546dbbcfbe8aea1944fc0b0ecbf531034bcd5b5770aSelim Cinek endClosing(); 547dbbcfbe8aea1944fc0b0ecbf531034bcd5b5770aSelim Cinek } 548dbbcfbe8aea1944fc0b0ecbf531034bcd5b5770aSelim Cinek 549dbbcfbe8aea1944fc0b0ecbf531034bcd5b5770aSelim Cinek private void endClosing() { 550dbbcfbe8aea1944fc0b0ecbf531034bcd5b5770aSelim Cinek if (mClosing) { 551dbbcfbe8aea1944fc0b0ecbf531034bcd5b5770aSelim Cinek mClosing = false; 552dbbcfbe8aea1944fc0b0ecbf531034bcd5b5770aSelim Cinek onClosingFinished(); 553dbbcfbe8aea1944fc0b0ecbf531034bcd5b5770aSelim Cinek } 554dbbcfbe8aea1944fc0b0ecbf531034bcd5b5770aSelim Cinek } 555dbbcfbe8aea1944fc0b0ecbf531034bcd5b5770aSelim Cinek 556b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek private void initVelocityTracker() { 557b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek if (mVelocityTracker != null) { 558b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek mVelocityTracker.recycle(); 559b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek } 560b7b61ddaef4f2a2ebc79e832fb909fd4dcac8ba5Jorim Jaggi mVelocityTracker = VelocityTrackerFactory.obtain(getContext()); 561b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek } 562b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek 563b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek protected boolean isScrolledToBottom() { 564172e914178181cf1c5999722fc0817e8ac2097f1Selim Cinek return true; 565b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek } 566b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek 567b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek protected float getContentHeight() { 568b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek return mExpandedHeight; 569bf526d14f3252b8a5c123291e4cd8b1c51346560Daniel Sandler } 570bf526d14f3252b8a5c123291e4cd8b1c51346560Daniel Sandler 57108d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler @Override 57208d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler protected void onFinishInflate() { 57308d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler super.onFinishInflate(); 574069cd03740312159faf24a01910ff1daeae93131Jorim Jaggi loadDimens(); 575069cd03740312159faf24a01910ff1daeae93131Jorim Jaggi } 5760c1b75c17b79979e0f210b5bf03226d1091a4c21Daniel Sandler 577069cd03740312159faf24a01910ff1daeae93131Jorim Jaggi @Override 578069cd03740312159faf24a01910ff1daeae93131Jorim Jaggi protected void onConfigurationChanged(Configuration newConfig) { 579069cd03740312159faf24a01910ff1daeae93131Jorim Jaggi super.onConfigurationChanged(newConfig); 58008d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler loadDimens(); 58108d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 58208d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 5832fbad7b6a724cf0a5b98b66fe639d58f5ab10af3Jorim Jaggi /** 584b7240136b748e548069c7fe2bd77a7ed4148728eJorim Jaggi * @param vel the current vertical velocity of the motion 585b7240136b748e548069c7fe2bd77a7ed4148728eJorim Jaggi * @param vectorVel the length of the vectorial velocity 586e29b2dbc762bfa66093d76f5a65f55328d8753c9Jorim Jaggi * @return whether a fling should expands the panel; contracts otherwise 5872fbad7b6a724cf0a5b98b66fe639d58f5ab10af3Jorim Jaggi */ 5889db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek protected boolean flingExpands(float vel, float vectorVel, float x, float y) { 5899db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek if (isFalseTouch(x, y)) { 59019c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek return true; 59119c8c708f16546fc75ae12659aa190f5e3dfbb52Selim Cinek } 592b7240136b748e548069c7fe2bd77a7ed4148728eJorim Jaggi if (Math.abs(vectorVel) < mFlingAnimationUtils.getMinVelocityPxPerSecond()) { 593e29b2dbc762bfa66093d76f5a65f55328d8753c9Jorim Jaggi return getExpandedFraction() > 0.5f; 5941d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi } else { 595e29b2dbc762bfa66093d76f5a65f55328d8753c9Jorim Jaggi return vel > 0; 5961d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi } 5971d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi } 59808d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 5999db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek /** 6009db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek * @param x the final x-coordinate when the finger was lifted 6019db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek * @param y the final y-coordinate when the finger was lifted 6029db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek * @return whether this motion should be regarded as a false touch 6039db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek */ 6049db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek private boolean isFalseTouch(float x, float y) { 6059db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek if (!mStatusBar.isFalsingThresholdNeeded()) { 6069db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek return false; 6079db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek } 6086dc59b48c040cf6871d7ff6d8e5242b1a5ddd032Blazej Magnowski if (mFalsingManager.isClassiferEnabled()) { 6096dc59b48c040cf6871d7ff6d8e5242b1a5ddd032Blazej Magnowski return mFalsingManager.isFalseTouch(); 6100e2ffbd48bbedf47deb7f6aed96bd07e2fc96f53Blazej Magnowski } 6119db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek if (!mTouchAboveFalsingThreshold) { 6129db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek return true; 6139db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek } 6149db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek if (mUpwardsWhenTresholdReached) { 6159db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek return false; 6169db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek } 6179db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek return !isDirectionUpwards(x, y); 6185386fb337d3f2bd9b0ea673b5f60483246e5d0cdSelim Cinek } 6195386fb337d3f2bd9b0ea673b5f60483246e5d0cdSelim Cinek 6201d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi protected void fling(float vel, boolean expand) { 6219db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek fling(vel, expand, 1.0f /* collapseSpeedUpFactor */, false); 6229db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek } 6239db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek 6249db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek protected void fling(float vel, boolean expand, boolean expandBecauseOfFalsing) { 6259db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek fling(vel, expand, 1.0f /* collapseSpeedUpFactor */, expandBecauseOfFalsing); 626f3b3bee12994a24b60bd447dede9e8791151fcc9Jorim Jaggi } 627f3b3bee12994a24b60bd447dede9e8791151fcc9Jorim Jaggi 6289db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek protected void fling(float vel, boolean expand, float collapseSpeedUpFactor, 6299db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek boolean expandBecauseOfFalsing) { 6301d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi cancelPeek(); 6311d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi float target = expand ? getMaxPanelHeight() : 0.0f; 6323e02adb028741938dab9787fa1552f86b2558c9aJorim Jaggi if (!expand) { 6333e02adb028741938dab9787fa1552f86b2558c9aJorim Jaggi mClosing = true; 6343e02adb028741938dab9787fa1552f86b2558c9aJorim Jaggi } 6359db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek flingToHeight(vel, expand, target, collapseSpeedUpFactor, expandBecauseOfFalsing); 636b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 6374b04a3a1649018e7f0fe11136d0b012a9eeb44eaJorim Jaggi 638f3b3bee12994a24b60bd447dede9e8791151fcc9Jorim Jaggi protected void flingToHeight(float vel, boolean expand, float target, 6399db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek float collapseSpeedUpFactor, boolean expandBecauseOfFalsing) { 6404b04a3a1649018e7f0fe11136d0b012a9eeb44eaJorim Jaggi // Hack to make the expand transition look nice when clear all button is visible - we make 6414b04a3a1649018e7f0fe11136d0b012a9eeb44eaJorim Jaggi // the animation only to the last notification, and then jump to the maximum panel height so 6424b04a3a1649018e7f0fe11136d0b012a9eeb44eaJorim Jaggi // clear all just fades in and the decelerating motion is towards the last notification. 6434b04a3a1649018e7f0fe11136d0b012a9eeb44eaJorim Jaggi final boolean clearAllExpandHack = expand && fullyExpandedClearAllVisible() 6444b04a3a1649018e7f0fe11136d0b012a9eeb44eaJorim Jaggi && mExpandedHeight < getMaxPanelHeight() - getClearAllHeight() 6454b04a3a1649018e7f0fe11136d0b012a9eeb44eaJorim Jaggi && !isClearAllVisible(); 6464b04a3a1649018e7f0fe11136d0b012a9eeb44eaJorim Jaggi if (clearAllExpandHack) { 6474b04a3a1649018e7f0fe11136d0b012a9eeb44eaJorim Jaggi target = getMaxPanelHeight() - getClearAllHeight(); 6484b04a3a1649018e7f0fe11136d0b012a9eeb44eaJorim Jaggi } 64947c85a3525dcd0bbd3168632830e8ab491d18462Jorim Jaggi if (target == mExpandedHeight || getOverExpansionAmount() > 0f && expand) { 650b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi notifyExpandingFinished(); 6512fbad7b6a724cf0a5b98b66fe639d58f5ab10af3Jorim Jaggi return; 6522fbad7b6a724cf0a5b98b66fe639d58f5ab10af3Jorim Jaggi } 65347c85a3525dcd0bbd3168632830e8ab491d18462Jorim Jaggi mOverExpandedBeforeFling = getOverExpansionAmount() > 0f; 6549012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi ValueAnimator animator = createHeightAnimator(target); 6551d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi if (expand) { 6569db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek if (expandBecauseOfFalsing) { 6575386fb337d3f2bd9b0ea673b5f60483246e5d0cdSelim Cinek vel = 0; 6585386fb337d3f2bd9b0ea673b5f60483246e5d0cdSelim Cinek } 6591d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi mFlingAnimationUtils.apply(animator, mExpandedHeight, target, vel, getHeight()); 6606626f54e658e3da44fab8a5cd6d9d3d4852e2cd1Jorim Jaggi if (vel == 0) { 6615386fb337d3f2bd9b0ea673b5f60483246e5d0cdSelim Cinek animator.setDuration(350); 6625386fb337d3f2bd9b0ea673b5f60483246e5d0cdSelim Cinek } 6631685e634fb0b14033bd436af8d7174436699ffecSelim Cinek } else { 6641d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi mFlingAnimationUtils.applyDismissing(animator, mExpandedHeight, target, vel, 6651d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi getHeight()); 6661d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi 6671d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi // Make it shorter if we run a canned animation 6681d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi if (vel == 0) { 66930c305ce6283ce1380ad91ef0d221696b32d5a6bJorim Jaggi animator.setDuration((long) 670f3b3bee12994a24b60bd447dede9e8791151fcc9Jorim Jaggi (animator.getDuration() * getCannedFlingDurationFactor() 671f3b3bee12994a24b60bd447dede9e8791151fcc9Jorim Jaggi / collapseSpeedUpFactor)); 6721d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi } 67308d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 6741d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi animator.addListener(new AnimatorListenerAdapter() { 675b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi private boolean mCancelled; 676b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi 677b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi @Override 678b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi public void onAnimationCancel(Animator animation) { 679b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi mCancelled = true; 680b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi } 681b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi 6821d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi @Override 6831d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi public void onAnimationEnd(Animator animation) { 6844b04a3a1649018e7f0fe11136d0b012a9eeb44eaJorim Jaggi if (clearAllExpandHack && !mCancelled) { 6852ae259df68659fd3c0c3ca070f58ca40b20de8b8Jorim Jaggi setExpandedHeightInternal(getMaxPanelHeight()); 6862ae259df68659fd3c0c3ca070f58ca40b20de8b8Jorim Jaggi } 6872ae259df68659fd3c0c3ca070f58ca40b20de8b8Jorim Jaggi mHeightAnimator = null; 6882ae259df68659fd3c0c3ca070f58ca40b20de8b8Jorim Jaggi if (!mCancelled) { 6892ae259df68659fd3c0c3ca070f58ca40b20de8b8Jorim Jaggi notifyExpandingFinished(); 690b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi } 691eb8f11a8657a1509d6c00b3c6f34547f803bbe67Jorim Jaggi notifyBarPanelExpansionChanged(); 6921d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi } 6931d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi }); 6941d480695df31f1c328473f32d5007cea6a03b6e0Jorim Jaggi mHeightAnimator = animator; 69547c85a3525dcd0bbd3168632830e8ab491d18462Jorim Jaggi animator.start(); 69608d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 69708d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 69808d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler @Override 69908d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler protected void onAttachedToWindow() { 70008d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler super.onAttachedToWindow(); 701978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler mViewName = getResources().getResourceName(getId()); 702978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler } 703978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler 704978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler public String getName() { 705978f853d189c1857190b4a2e200c7a283e31ca14Daniel Sandler return mViewName; 70608d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 70708d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 70808d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler public void setExpandedHeight(float height) { 7099764218ff979f735aee2f1189e3547d5f3b02f83John Spurlock if (DEBUG) logf("setExpandedHeight(%.1f)", height); 71047c85a3525dcd0bbd3168632830e8ab491d18462Jorim Jaggi setExpandedHeightInternal(height + getOverExpansionPixels()); 71108d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 71208d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 7135050813f15a1d39d49cb8eca5a3aa6df43c4d450Daniel Sandler @Override 7145050813f15a1d39d49cb8eca5a3aa6df43c4d450Daniel Sandler protected void onLayout (boolean changed, int left, int top, int right, int bottom) { 7155050813f15a1d39d49cb8eca5a3aa6df43c4d450Daniel Sandler super.onLayout(changed, left, top, right, bottom); 7165fbc632fefa8e4826d42a2ba43772f9f906153ffSelim Cinek mStatusBar.onPanelLaidOut(); 717b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek requestPanelHeightUpdate(); 71831094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek mHasLayoutedSinceDown = true; 71931094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek if (mUpdateFlingOnLayout) { 72031094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek abortAnimations(); 721b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek fling(mUpdateFlingVelocity, true /* expands */); 72231094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek mUpdateFlingOnLayout = false; 72331094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek } 724b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek } 725b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek 726b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek protected void requestPanelHeightUpdate() { 727b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek float currentMaxPanelHeight = getMaxPanelHeight(); 728b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek 729b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek // If the user isn't actively poking us, let's update the height 73030c305ce6283ce1380ad91ef0d221696b32d5a6bJorim Jaggi if ((!mTracking || isTrackingBlocked()) 73130c305ce6283ce1380ad91ef0d221696b32d5a6bJorim Jaggi && mHeightAnimator == null 732684a442b812a5e95d813700ffa2fd17ca72048a7Selim Cinek && !isFullyCollapsed() 73330c305ce6283ce1380ad91ef0d221696b32d5a6bJorim Jaggi && currentMaxPanelHeight != mExpandedHeight 73430c305ce6283ce1380ad91ef0d221696b32d5a6bJorim Jaggi && !mPeekPending 73531094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek && mPeekAnimator == null 736b7a3303f807ee01bbe405f4153a2285e55c0b6e3Jorim Jaggi && !mPeekTouching) { 73747c85a3525dcd0bbd3168632830e8ab491d18462Jorim Jaggi setExpandedHeight(currentMaxPanelHeight); 738b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek } 7395050813f15a1d39d49cb8eca5a3aa6df43c4d450Daniel Sandler } 7405050813f15a1d39d49cb8eca5a3aa6df43c4d450Daniel Sandler 74108d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler public void setExpandedHeightInternal(float h) { 74247c85a3525dcd0bbd3168632830e8ab491d18462Jorim Jaggi float fhWithoutOverExpansion = getMaxPanelHeight() - getOverExpansionAmount(); 74347c85a3525dcd0bbd3168632830e8ab491d18462Jorim Jaggi if (mHeightAnimator == null) { 74447c85a3525dcd0bbd3168632830e8ab491d18462Jorim Jaggi float overExpansionPixels = Math.max(0, h - fhWithoutOverExpansion); 74547c85a3525dcd0bbd3168632830e8ab491d18462Jorim Jaggi if (getOverExpansionPixels() != overExpansionPixels && mTracking) { 74647c85a3525dcd0bbd3168632830e8ab491d18462Jorim Jaggi setOverExpansion(overExpansionPixels, true /* isPixels */); 74747c85a3525dcd0bbd3168632830e8ab491d18462Jorim Jaggi } 74847c85a3525dcd0bbd3168632830e8ab491d18462Jorim Jaggi mExpandedHeight = Math.min(h, fhWithoutOverExpansion) + getOverExpansionAmount(); 74947c85a3525dcd0bbd3168632830e8ab491d18462Jorim Jaggi } else { 75047c85a3525dcd0bbd3168632830e8ab491d18462Jorim Jaggi mExpandedHeight = h; 75147c85a3525dcd0bbd3168632830e8ab491d18462Jorim Jaggi if (mOverExpandedBeforeFling) { 75247c85a3525dcd0bbd3168632830e8ab491d18462Jorim Jaggi setOverExpansion(Math.max(0, h - fhWithoutOverExpansion), false /* isPixels */); 75347c85a3525dcd0bbd3168632830e8ab491d18462Jorim Jaggi } 754b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek } 755b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek 75693439da0ed9213bc54291b3fce4e04dd3a7f9f3aJorim Jaggi mExpandedHeight = Math.max(0, mExpandedHeight); 75747c85a3525dcd0bbd3168632830e8ab491d18462Jorim Jaggi mExpandedFraction = Math.min(1f, fhWithoutOverExpansion == 0 75847c85a3525dcd0bbd3168632830e8ab491d18462Jorim Jaggi ? 0 75947c85a3525dcd0bbd3168632830e8ab491d18462Jorim Jaggi : mExpandedHeight / fhWithoutOverExpansion); 76006a0c3a4459de084ecf8f1a8920edf36c41ac164Jorim Jaggi onHeightUpdated(mExpandedHeight); 761b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi notifyBarPanelExpansionChanged(); 76208d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 76308d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 76430c305ce6283ce1380ad91ef0d221696b32d5a6bJorim Jaggi /** 76530c305ce6283ce1380ad91ef0d221696b32d5a6bJorim Jaggi * @return true if the panel tracking should be temporarily blocked; this is used when a 76630c305ce6283ce1380ad91ef0d221696b32d5a6bJorim Jaggi * conflicting gesture (opening QS) is happening 76730c305ce6283ce1380ad91ef0d221696b32d5a6bJorim Jaggi */ 76830c305ce6283ce1380ad91ef0d221696b32d5a6bJorim Jaggi protected abstract boolean isTrackingBlocked(); 76930c305ce6283ce1380ad91ef0d221696b32d5a6bJorim Jaggi 77047c85a3525dcd0bbd3168632830e8ab491d18462Jorim Jaggi protected abstract void setOverExpansion(float overExpansion, boolean isPixels); 77124120a5ccf79f6f4844916121bcc1fbad0b7691bSelim Cinek 7729012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi protected abstract void onHeightUpdated(float expandedHeight); 773b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek 77447c85a3525dcd0bbd3168632830e8ab491d18462Jorim Jaggi protected abstract float getOverExpansionAmount(); 77547c85a3525dcd0bbd3168632830e8ab491d18462Jorim Jaggi 77647c85a3525dcd0bbd3168632830e8ab491d18462Jorim Jaggi protected abstract float getOverExpansionPixels(); 77747c85a3525dcd0bbd3168632830e8ab491d18462Jorim Jaggi 778b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek /** 779b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek * This returns the maximum height of the panel. Children should override this if their 780b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek * desired height is not the full height. 781b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek * 782b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek * @return the default implementation simply returns the maximum height. 783b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek */ 78431094df5c6e3cb3a4a4faacb091e35eea1f6a5deSelim Cinek protected abstract int getMaxPanelHeight(); 78508d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 78608d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler public void setExpandedFraction(float frac) { 787b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek setExpandedHeight(getMaxPanelHeight() * frac); 78808d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 78908d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 79008d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler public float getExpandedHeight() { 79108d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler return mExpandedHeight; 79208d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 79308d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 79408d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler public float getExpandedFraction() { 79508d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler return mExpandedFraction; 79608d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 79708d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 798b4e56edde684c2a09cb225c99571fddb39b43b34Daniel Sandler public boolean isFullyExpanded() { 799b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek return mExpandedHeight >= getMaxPanelHeight(); 800b4e56edde684c2a09cb225c99571fddb39b43b34Daniel Sandler } 801b4e56edde684c2a09cb225c99571fddb39b43b34Daniel Sandler 802b4e56edde684c2a09cb225c99571fddb39b43b34Daniel Sandler public boolean isFullyCollapsed() { 80367eab79051eea2d4f8fda4a2a698900ffacfb557Daniel Sandler return mExpandedHeight <= 0; 80467eab79051eea2d4f8fda4a2a698900ffacfb557Daniel Sandler } 80567eab79051eea2d4f8fda4a2a698900ffacfb557Daniel Sandler 80667eab79051eea2d4f8fda4a2a698900ffacfb557Daniel Sandler public boolean isCollapsing() { 80767eab79051eea2d4f8fda4a2a698900ffacfb557Daniel Sandler return mClosing; 808b4e56edde684c2a09cb225c99571fddb39b43b34Daniel Sandler } 809b4e56edde684c2a09cb225c99571fddb39b43b34Daniel Sandler 810a4b70aff3419b61d2395589b393251da9ddcba3fJohn Spurlock public boolean isTracking() { 811a4b70aff3419b61d2395589b393251da9ddcba3fJohn Spurlock return mTracking; 812a4b70aff3419b61d2395589b393251da9ddcba3fJohn Spurlock } 813a4b70aff3419b61d2395589b393251da9ddcba3fJohn Spurlock 81408d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler public void setBar(PanelBar panelBar) { 81508d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler mBar = panelBar; 81608d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 81708d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 818f3b3bee12994a24b60bd447dede9e8791151fcc9Jorim Jaggi public void collapse(boolean delayed, float speedUpFactor) { 8199764218ff979f735aee2f1189e3547d5f3b02f83John Spurlock if (DEBUG) logf("collapse: " + this); 820b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi if (mPeekPending || mPeekAnimator != null) { 821b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi mCollapseAfterPeek = true; 822b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi if (mPeekPending) { 823b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi 824b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi // We know that the whole gesture is just a peek triggered by a simple click, so 825b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi // better start it now. 826b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi removeCallbacks(mPeekRunnable); 827b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi mPeekRunnable.run(); 828b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi } 82998139559af15d85b8a34c02fe9bc97fba901a4b5Jorim Jaggi } else if (!isFullyCollapsed() && !mTracking && !mClosing) { 830dbbcfbe8aea1944fc0b0ecbf531034bcd5b5770aSelim Cinek cancelHeightAnimator(); 831b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi notifyExpandingStarted(); 8323b866bee86f742f51a0042985ec7666283dc4406Jorim Jaggi 8333b866bee86f742f51a0042985ec7666283dc4406Jorim Jaggi // Set after notifyExpandingStarted, as notifyExpandingStarted resets the closing state. 8343b866bee86f742f51a0042985ec7666283dc4406Jorim Jaggi mClosing = true; 8358de4311c51229efbe2f2d0afbf298982c5cadd96Jorim Jaggi if (delayed) { 836f3b3bee12994a24b60bd447dede9e8791151fcc9Jorim Jaggi mNextCollapseSpeedUpFactor = speedUpFactor; 8375cbfe5476b1422c63363c6899d455870bed15663Jorim Jaggi postDelayed(mFlingCollapseRunnable, 120); 8388de4311c51229efbe2f2d0afbf298982c5cadd96Jorim Jaggi } else { 8399db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek fling(0, false /* expand */, speedUpFactor, false /* expandBecauseOfFalsing */); 8408de4311c51229efbe2f2d0afbf298982c5cadd96Jorim Jaggi } 84108d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 84208d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 84308d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler 8445cbfe5476b1422c63363c6899d455870bed15663Jorim Jaggi private final Runnable mFlingCollapseRunnable = new Runnable() { 8455cbfe5476b1422c63363c6899d455870bed15663Jorim Jaggi @Override 8465cbfe5476b1422c63363c6899d455870bed15663Jorim Jaggi public void run() { 8479db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek fling(0, false /* expand */, mNextCollapseSpeedUpFactor, 8489db71054b83a650f3478c9335634b611ddaf53bfSelim Cinek false /* expandBecauseOfFalsing */); 8495cbfe5476b1422c63363c6899d455870bed15663Jorim Jaggi } 8505cbfe5476b1422c63363c6899d455870bed15663Jorim Jaggi }; 8515cbfe5476b1422c63363c6899d455870bed15663Jorim Jaggi 8529764218ff979f735aee2f1189e3547d5f3b02f83John Spurlock public void cancelPeek() { 853529c5325f0e5cd3cf97fd7431d8dc9e79d7a627fSelim Cinek boolean cancelled = mPeekPending; 854b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi if (mPeekAnimator != null) { 855529c5325f0e5cd3cf97fd7431d8dc9e79d7a627fSelim Cinek cancelled = true; 8569764218ff979f735aee2f1189e3547d5f3b02f83John Spurlock mPeekAnimator.cancel(); 85708d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 858b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi removeCallbacks(mPeekRunnable); 859b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi mPeekPending = false; 860b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi 861529c5325f0e5cd3cf97fd7431d8dc9e79d7a627fSelim Cinek if (cancelled) { 862529c5325f0e5cd3cf97fd7431d8dc9e79d7a627fSelim Cinek // When peeking, we already tell mBar that we expanded ourselves. Make sure that we also 863529c5325f0e5cd3cf97fd7431d8dc9e79d7a627fSelim Cinek // notify mBar that we might have closed ourselves. 864529c5325f0e5cd3cf97fd7431d8dc9e79d7a627fSelim Cinek notifyBarPanelExpansionChanged(); 865529c5325f0e5cd3cf97fd7431d8dc9e79d7a627fSelim Cinek } 86608d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler } 86737a38aaecb5045906ade6d1c970f106a028cbaf5Daniel Sandler 8688d3fea15b80ac4fab7abe7a7a07c6368166de5e1Oren Blasberg public void expand(final boolean animate) { 8698d3fea15b80ac4fab7abe7a7a07c6368166de5e1Oren Blasberg if (!isFullyCollapsed() && !isCollapsing()) { 8708d3fea15b80ac4fab7abe7a7a07c6368166de5e1Oren Blasberg return; 8718d3fea15b80ac4fab7abe7a7a07c6368166de5e1Oren Blasberg } 8728d3fea15b80ac4fab7abe7a7a07c6368166de5e1Oren Blasberg 8730a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi mInstantExpanding = true; 8746626f54e658e3da44fab8a5cd6d9d3d4852e2cd1Jorim Jaggi mAnimateAfterExpanding = animate; 8755cbfe5476b1422c63363c6899d455870bed15663Jorim Jaggi mUpdateFlingOnLayout = false; 8760a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi abortAnimations(); 8775cbfe5476b1422c63363c6899d455870bed15663Jorim Jaggi cancelPeek(); 8780a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi if (mTracking) { 8790a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi onTrackingStopped(true /* expands */); // The panel is expanded after this call. 880e62d589bea54e58054ae16265c92e974a8250ff5Jorim Jaggi } 881e62d589bea54e58054ae16265c92e974a8250ff5Jorim Jaggi if (mExpanding) { 882b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi notifyExpandingFinished(); 8830a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi } 884b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek notifyBarPanelExpansionChanged(); 8850a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi 8860a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi // Wait for window manager to pickup the change, so we know the maximum height of the panel 8870a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi // then. 8880a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi getViewTreeObserver().addOnGlobalLayoutListener( 8890a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi new ViewTreeObserver.OnGlobalLayoutListener() { 8900a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi @Override 8910a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi public void onGlobalLayout() { 892c5804afa73edbf229e789570d288e66f70b54fa2Jorim Jaggi if (!mInstantExpanding) { 893c5804afa73edbf229e789570d288e66f70b54fa2Jorim Jaggi getViewTreeObserver().removeOnGlobalLayoutListener(this); 894c5804afa73edbf229e789570d288e66f70b54fa2Jorim Jaggi return; 895c5804afa73edbf229e789570d288e66f70b54fa2Jorim Jaggi } 8960a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi if (mStatusBar.getStatusBarWindow().getHeight() 8970a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi != mStatusBar.getStatusBarHeight()) { 8980a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi getViewTreeObserver().removeOnGlobalLayoutListener(this); 8996626f54e658e3da44fab8a5cd6d9d3d4852e2cd1Jorim Jaggi if (mAnimateAfterExpanding) { 9008d3fea15b80ac4fab7abe7a7a07c6368166de5e1Oren Blasberg notifyExpandingStarted(); 9018d3fea15b80ac4fab7abe7a7a07c6368166de5e1Oren Blasberg fling(0, true /* expand */); 9028d3fea15b80ac4fab7abe7a7a07c6368166de5e1Oren Blasberg } else { 9038d3fea15b80ac4fab7abe7a7a07c6368166de5e1Oren Blasberg setExpandedFraction(1f); 9048d3fea15b80ac4fab7abe7a7a07c6368166de5e1Oren Blasberg } 9050a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi mInstantExpanding = false; 9060a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi } 9070a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi } 9080a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi }); 9090a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi 9100a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi // Make sure a layout really happens. 9110a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi requestLayout(); 9120a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi } 9130a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi 9146bb4a9b356bdb141e353a8115e100029bed3eb88Selim Cinek public void instantCollapse() { 9156bb4a9b356bdb141e353a8115e100029bed3eb88Selim Cinek abortAnimations(); 9166bb4a9b356bdb141e353a8115e100029bed3eb88Selim Cinek setExpandedFraction(0f); 9176bb4a9b356bdb141e353a8115e100029bed3eb88Selim Cinek if (mExpanding) { 9186bb4a9b356bdb141e353a8115e100029bed3eb88Selim Cinek notifyExpandingFinished(); 9196bb4a9b356bdb141e353a8115e100029bed3eb88Selim Cinek } 920c5804afa73edbf229e789570d288e66f70b54fa2Jorim Jaggi if (mInstantExpanding) { 921c5804afa73edbf229e789570d288e66f70b54fa2Jorim Jaggi mInstantExpanding = false; 922c5804afa73edbf229e789570d288e66f70b54fa2Jorim Jaggi notifyBarPanelExpansionChanged(); 923c5804afa73edbf229e789570d288e66f70b54fa2Jorim Jaggi } 9246bb4a9b356bdb141e353a8115e100029bed3eb88Selim Cinek } 9256bb4a9b356bdb141e353a8115e100029bed3eb88Selim Cinek 9260a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi private void abortAnimations() { 9270a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi cancelPeek(); 928dbbcfbe8aea1944fc0b0ecbf531034bcd5b5770aSelim Cinek cancelHeightAnimator(); 9295cbfe5476b1422c63363c6899d455870bed15663Jorim Jaggi removeCallbacks(mPostCollapseRunnable); 9305cbfe5476b1422c63363c6899d455870bed15663Jorim Jaggi removeCallbacks(mFlingCollapseRunnable); 9310a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi } 9320a27be899c7143df1d8b64ef842b7f6b7fcf0baaJorim Jaggi 933dbbcfbe8aea1944fc0b0ecbf531034bcd5b5770aSelim Cinek protected void onClosingFinished() { 934dbbcfbe8aea1944fc0b0ecbf531034bcd5b5770aSelim Cinek mBar.onClosingFinished(); 935dbbcfbe8aea1944fc0b0ecbf531034bcd5b5770aSelim Cinek } 936dbbcfbe8aea1944fc0b0ecbf531034bcd5b5770aSelim Cinek 937dbbcfbe8aea1944fc0b0ecbf531034bcd5b5770aSelim Cinek 9389012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi protected void startUnlockHintAnimation() { 9399012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi 9409012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi // We don't need to hint the user if an animation is already running or the user is changing 9419012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi // the expansion. 9429012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi if (mHeightAnimator != null || mTracking) { 9439012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi return; 9449012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi } 9459012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi cancelPeek(); 946b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi notifyExpandingStarted(); 947b3f0a2ff000ca2481f95ee8f7d7b487e33b87ecaJorim Jaggi startUnlockHintAnimationPhase1(new Runnable() { 948b3f0a2ff000ca2481f95ee8f7d7b487e33b87ecaJorim Jaggi @Override 949b3f0a2ff000ca2481f95ee8f7d7b487e33b87ecaJorim Jaggi public void run() { 950b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi notifyExpandingFinished(); 951b3f0a2ff000ca2481f95ee8f7d7b487e33b87ecaJorim Jaggi mStatusBar.onHintFinished(); 952b3f0a2ff000ca2481f95ee8f7d7b487e33b87ecaJorim Jaggi mHintAnimationRunning = false; 953b3f0a2ff000ca2481f95ee8f7d7b487e33b87ecaJorim Jaggi } 954b3f0a2ff000ca2481f95ee8f7d7b487e33b87ecaJorim Jaggi }); 9559012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi mStatusBar.onUnlockHintStarted(); 956b3f0a2ff000ca2481f95ee8f7d7b487e33b87ecaJorim Jaggi mHintAnimationRunning = true; 9579012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi } 9589012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi 9599012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi /** 9609012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi * Phase 1: Move everything upwards. 9619012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi */ 962b3f0a2ff000ca2481f95ee8f7d7b487e33b87ecaJorim Jaggi private void startUnlockHintAnimationPhase1(final Runnable onAnimationFinished) { 9639012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi float target = Math.max(0, getMaxPanelHeight() - mHintDistance); 9649012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi ValueAnimator animator = createHeightAnimator(target); 9659012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi animator.setDuration(250); 966c18010f6720f606003cde3cd376ddacaca30f6e5Selim Cinek animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN); 9679012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi animator.addListener(new AnimatorListenerAdapter() { 9689012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi private boolean mCancelled; 9699012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi 9709012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi @Override 9719012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi public void onAnimationCancel(Animator animation) { 9729012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi mCancelled = true; 9739012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi } 9749012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi 9759012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi @Override 9769012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi public void onAnimationEnd(Animator animation) { 9779012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi if (mCancelled) { 9789012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi mHeightAnimator = null; 979b3f0a2ff000ca2481f95ee8f7d7b487e33b87ecaJorim Jaggi onAnimationFinished.run(); 9809012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi } else { 981b3f0a2ff000ca2481f95ee8f7d7b487e33b87ecaJorim Jaggi startUnlockHintAnimationPhase2(onAnimationFinished); 9829012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi } 9839012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi } 9849012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi }); 9859012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi animator.start(); 9869012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi mHeightAnimator = animator; 987f99d0007646781b99a63bc0d2103a45f0f72e724Selim Cinek mKeyguardBottomArea.getIndicationView().animate() 9885256d93121d03b8d23053eead8c11bb3c43db109Selim Cinek .translationY(-mHintDistance) 989f99d0007646781b99a63bc0d2103a45f0f72e724Selim Cinek .setDuration(250) 990c18010f6720f606003cde3cd376ddacaca30f6e5Selim Cinek .setInterpolator(Interpolators.FAST_OUT_SLOW_IN) 991f99d0007646781b99a63bc0d2103a45f0f72e724Selim Cinek .withEndAction(new Runnable() { 992f99d0007646781b99a63bc0d2103a45f0f72e724Selim Cinek @Override 993f99d0007646781b99a63bc0d2103a45f0f72e724Selim Cinek public void run() { 994f99d0007646781b99a63bc0d2103a45f0f72e724Selim Cinek mKeyguardBottomArea.getIndicationView().animate() 9955256d93121d03b8d23053eead8c11bb3c43db109Selim Cinek .translationY(0) 996f99d0007646781b99a63bc0d2103a45f0f72e724Selim Cinek .setDuration(450) 997f99d0007646781b99a63bc0d2103a45f0f72e724Selim Cinek .setInterpolator(mBounceInterpolator) 998f99d0007646781b99a63bc0d2103a45f0f72e724Selim Cinek .start(); 999f99d0007646781b99a63bc0d2103a45f0f72e724Selim Cinek } 1000f99d0007646781b99a63bc0d2103a45f0f72e724Selim Cinek }) 1001f99d0007646781b99a63bc0d2103a45f0f72e724Selim Cinek .start(); 10029012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi } 10039012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi 10049012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi /** 10059012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi * Phase 2: Bounce down. 10069012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi */ 1007b3f0a2ff000ca2481f95ee8f7d7b487e33b87ecaJorim Jaggi private void startUnlockHintAnimationPhase2(final Runnable onAnimationFinished) { 10089012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi ValueAnimator animator = createHeightAnimator(getMaxPanelHeight()); 10099012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi animator.setDuration(450); 10109012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi animator.setInterpolator(mBounceInterpolator); 10119012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi animator.addListener(new AnimatorListenerAdapter() { 10129012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi @Override 10139012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi public void onAnimationEnd(Animator animation) { 10149012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi mHeightAnimator = null; 1015b3f0a2ff000ca2481f95ee8f7d7b487e33b87ecaJorim Jaggi onAnimationFinished.run(); 1016eb8f11a8657a1509d6c00b3c6f34547f803bbe67Jorim Jaggi notifyBarPanelExpansionChanged(); 10179012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi } 10189012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi }); 10199012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi animator.start(); 10209012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi mHeightAnimator = animator; 10219012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi } 10229012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi 10239012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi private ValueAnimator createHeightAnimator(float targetHeight) { 10249012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi ValueAnimator animator = ValueAnimator.ofFloat(mExpandedHeight, targetHeight); 10259012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 10269012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi @Override 10279012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi public void onAnimationUpdate(ValueAnimator animation) { 102847c85a3525dcd0bbd3168632830e8ab491d18462Jorim Jaggi setExpandedHeightInternal((Float) animation.getAnimatedValue()); 10299012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi } 10309012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi }); 10319012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi return animator; 10329012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi } 10339012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi 1034b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek protected void notifyBarPanelExpansionChanged() { 10359f96711e1adf4a28f961c440da1626ad40c03bc8Xiaohui Chen mBar.panelExpansionChanged(mExpandedFraction, mExpandedFraction > 0f || mPeekPending 10360fccc729fd3b19a62efd90ae13b207faa3d1e8bbSelim Cinek || mPeekAnimator != null || mInstantExpanding || isPanelVisibleBecauseOfHeadsUp() 1037eb8f11a8657a1509d6c00b3c6f34547f803bbe67Jorim Jaggi || mTracking || mHeightAnimator != null); 1038b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi } 1039b472b347b51f84489217bb5d9c3beeeda1e4e626Jorim Jaggi 10400fccc729fd3b19a62efd90ae13b207faa3d1e8bbSelim Cinek protected abstract boolean isPanelVisibleBecauseOfHeadsUp(); 10410fccc729fd3b19a62efd90ae13b207faa3d1e8bbSelim Cinek 10429012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi /** 10439012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi * Gets called when the user performs a click anywhere in the empty area of the panel. 10449012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi * 10459012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi * @return whether the panel will be expanded after the action performed by this method 10469012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi */ 10473a9c10a2861404f1be9f06a3a54ae18803c81d1dSelim Cinek protected boolean onEmptySpaceClick(float x) { 1048b3f0a2ff000ca2481f95ee8f7d7b487e33b87ecaJorim Jaggi if (mHintAnimationRunning) { 1049b3f0a2ff000ca2481f95ee8f7d7b487e33b87ecaJorim Jaggi return true; 1050b3f0a2ff000ca2481f95ee8f7d7b487e33b87ecaJorim Jaggi } 10516746c28b812446e847fbfec0f54025558584e70aSelim Cinek return onMiddleClicked(); 1052b3f0a2ff000ca2481f95ee8f7d7b487e33b87ecaJorim Jaggi } 1053b3f0a2ff000ca2481f95ee8f7d7b487e33b87ecaJorim Jaggi 10541cf6e101263e17c9469c12b4befe36280c109de0Jorim Jaggi protected final Runnable mPostCollapseRunnable = new Runnable() { 1055488b792eeeea359ba29addd6a202b5475ad1d18fJorim Jaggi @Override 1056488b792eeeea359ba29addd6a202b5475ad1d18fJorim Jaggi public void run() { 1057f3b3bee12994a24b60bd447dede9e8791151fcc9Jorim Jaggi collapse(false /* delayed */, 1.0f /* speedUpFactor */); 1058488b792eeeea359ba29addd6a202b5475ad1d18fJorim Jaggi } 1059488b792eeeea359ba29addd6a202b5475ad1d18fJorim Jaggi }; 1060488b792eeeea359ba29addd6a202b5475ad1d18fJorim Jaggi 10611cf6e101263e17c9469c12b4befe36280c109de0Jorim Jaggi protected abstract boolean onMiddleClicked(); 10629012958742c7a66b37ba5f2196f9086bb1980e6bJorim Jaggi 1063d7912d2f106053bf4965d137b436e0b5b863f184Jorim Jaggi protected abstract boolean isDozing(); 1064d7912d2f106053bf4965d137b436e0b5b863f184Jorim Jaggi 106537a38aaecb5045906ade6d1c970f106a028cbaf5Daniel Sandler public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1066a3e5bcb60efdf1202f627d25d30693089f7d535dSelim Cinek pw.println(String.format("[PanelView(%s): expandedHeight=%f maxPanelHeight=%d closing=%s" 106750d87a7fb4fd146112ce1b080d618f67fe08884bJorim Jaggi + " tracking=%s justPeeked=%s peekAnim=%s%s timeAnim=%s%s touchDisabled=%s" 106837a38aaecb5045906ade6d1c970f106a028cbaf5Daniel Sandler + "]", 106937a38aaecb5045906ade6d1c970f106a028cbaf5Daniel Sandler this.getClass().getSimpleName(), 107037a38aaecb5045906ade6d1c970f106a028cbaf5Daniel Sandler getExpandedHeight(), 1071b6d85ebfe4f9f5d3b7d7ab7b6123af02a0deb516Selim Cinek getMaxPanelHeight(), 107237a38aaecb5045906ade6d1c970f106a028cbaf5Daniel Sandler mClosing?"T":"f", 107337a38aaecb5045906ade6d1c970f106a028cbaf5Daniel Sandler mTracking?"T":"f", 107437a38aaecb5045906ade6d1c970f106a028cbaf5Daniel Sandler mJustPeeked?"T":"f", 107537a38aaecb5045906ade6d1c970f106a028cbaf5Daniel Sandler mPeekAnimator, ((mPeekAnimator!=null && mPeekAnimator.isStarted())?" (started)":""), 107650d87a7fb4fd146112ce1b080d618f67fe08884bJorim Jaggi mHeightAnimator, ((mHeightAnimator !=null && mHeightAnimator.isStarted())?" (started)":""), 107750d87a7fb4fd146112ce1b080d618f67fe08884bJorim Jaggi mTouchDisabled?"T":"f" 107837a38aaecb5045906ade6d1c970f106a028cbaf5Daniel Sandler )); 107937a38aaecb5045906ade6d1c970f106a028cbaf5Daniel Sandler } 10803c4635c19997748e0b21453f3462e347905534e0Selim Cinek 10813c4635c19997748e0b21453f3462e347905534e0Selim Cinek public abstract void resetViews(); 10822580a976ec93a01ed00fae51364ad872bc591d95Jorim Jaggi 10832580a976ec93a01ed00fae51364ad872bc591d95Jorim Jaggi protected abstract float getPeekHeight(); 108430c305ce6283ce1380ad91ef0d221696b32d5a6bJorim Jaggi 108530c305ce6283ce1380ad91ef0d221696b32d5a6bJorim Jaggi protected abstract float getCannedFlingDurationFactor(); 10864b04a3a1649018e7f0fe11136d0b012a9eeb44eaJorim Jaggi 10874b04a3a1649018e7f0fe11136d0b012a9eeb44eaJorim Jaggi /** 10884b04a3a1649018e7f0fe11136d0b012a9eeb44eaJorim Jaggi * @return whether "Clear all" button will be visible when the panel is fully expanded 10894b04a3a1649018e7f0fe11136d0b012a9eeb44eaJorim Jaggi */ 10904b04a3a1649018e7f0fe11136d0b012a9eeb44eaJorim Jaggi protected abstract boolean fullyExpandedClearAllVisible(); 10914b04a3a1649018e7f0fe11136d0b012a9eeb44eaJorim Jaggi 10924b04a3a1649018e7f0fe11136d0b012a9eeb44eaJorim Jaggi protected abstract boolean isClearAllVisible(); 10934b04a3a1649018e7f0fe11136d0b012a9eeb44eaJorim Jaggi 10944b04a3a1649018e7f0fe11136d0b012a9eeb44eaJorim Jaggi /** 10954b04a3a1649018e7f0fe11136d0b012a9eeb44eaJorim Jaggi * @return the height of the clear all button, in pixels 10964b04a3a1649018e7f0fe11136d0b012a9eeb44eaJorim Jaggi */ 10974b04a3a1649018e7f0fe11136d0b012a9eeb44eaJorim Jaggi protected abstract int getClearAllHeight(); 1098b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek 1099b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek public void setHeadsUpManager(HeadsUpManager headsUpManager) { 1100b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek mHeadsUpManager = headsUpManager; 1101b8f09cf5533d458868a335ce334e4880b2b0788dSelim Cinek } 110208d05e3d1d6ade6924266296033981a96b47d5fbDaniel Sandler} 1103