18bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi/* 28bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi * Copyright (C) 2014 The Android Open Source Project 38bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi * 48bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi * Licensed under the Apache License, Version 2.0 (the "License"); 58bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi * you may not use this file except in compliance with the License. 68bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi * You may obtain a copy of the License at 78bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi * 88bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi * http://www.apache.org/licenses/LICENSE-2.0 98bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi * 108bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi * Unless required by applicable law or agreed to in writing, software 118bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi * distributed under the License is distributed on an "AS IS" BASIS, 128bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi * See the License for the specific language governing permissions and 148bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi * limitations under the License 158bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi */ 168bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi 178bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggipackage com.android.systemui.qs; 188bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi 19e1be342615db772ff11d369150349dbd874076f1Jason Monkimport android.animation.Animator; 20e1be342615db772ff11d369150349dbd874076f1Jason Monkimport android.animation.AnimatorListenerAdapter; 218bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggiimport android.content.Context; 228b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monkimport android.graphics.Point; 23f7d9c49223c4f2fd8a498160914d41801e6b10eaJason Monkimport android.graphics.Rect; 248bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggiimport android.util.AttributeSet; 25e1be342615db772ff11d369150349dbd874076f1Jason Monkimport android.util.Log; 26e1be342615db772ff11d369150349dbd874076f1Jason Monkimport android.view.View; 27e1be342615db772ff11d369150349dbd874076f1Jason Monkimport android.view.ViewTreeObserver; 288bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggiimport android.widget.FrameLayout; 29e1be342615db772ff11d369150349dbd874076f1Jason Monkimport com.android.systemui.Interpolators; 308bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggiimport com.android.systemui.R; 318b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monkimport com.android.systemui.qs.customize.QSCustomizer; 32e1be342615db772ff11d369150349dbd874076f1Jason Monkimport com.android.systemui.statusbar.phone.BaseStatusBarHeader; 338b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monkimport com.android.systemui.statusbar.phone.NotificationPanelView; 34162011ebe8015f44d4d9ced519297a7cfb087af2Jason Monkimport com.android.systemui.statusbar.phone.QSTileHost; 35e1be342615db772ff11d369150349dbd874076f1Jason Monkimport com.android.systemui.statusbar.stack.StackStateAnimator; 368bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi 378bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi/** 38e1be342615db772ff11d369150349dbd874076f1Jason Monk * Wrapper view with background which contains {@link QSPanel} and {@link BaseStatusBarHeader} 39e1be342615db772ff11d369150349dbd874076f1Jason Monk * 40e1be342615db772ff11d369150349dbd874076f1Jason Monk * Also manages animations for the QS Header and Panel. 418bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi */ 428bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggipublic class QSContainer extends FrameLayout { 43e1be342615db772ff11d369150349dbd874076f1Jason Monk private static final String TAG = "QSContainer"; 44e1be342615db772ff11d369150349dbd874076f1Jason Monk private static final boolean DEBUG = false; 458bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi 468b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk private final Point mSizePoint = new Point(); 47f7d9c49223c4f2fd8a498160914d41801e6b10eaJason Monk private final Rect mQsBounds = new Rect(); 488b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk 498bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi private int mHeightOverride = -1; 504fe4a409bca01e16c807f3f76633afc1d9797e2aMuyuan Li protected QSPanel mQSPanel; 51377e7ad8dc0562c6f445594288e451c377824e4cJason Monk private QSDetail mQSDetail; 52e1be342615db772ff11d369150349dbd874076f1Jason Monk protected BaseStatusBarHeader mHeader; 534fe4a409bca01e16c807f3f76633afc1d9797e2aMuyuan Li protected float mQsExpansion; 54e1be342615db772ff11d369150349dbd874076f1Jason Monk private boolean mQsExpanded; 55e1be342615db772ff11d369150349dbd874076f1Jason Monk private boolean mHeaderAnimating; 56e1be342615db772ff11d369150349dbd874076f1Jason Monk private boolean mKeyguardShowing; 57e1be342615db772ff11d369150349dbd874076f1Jason Monk private boolean mStackScrollerOverscrolling; 58e1be342615db772ff11d369150349dbd874076f1Jason Monk 59e1be342615db772ff11d369150349dbd874076f1Jason Monk private long mDelay; 60162011ebe8015f44d4d9ced519297a7cfb087af2Jason Monk private QSAnimator mQSAnimator; 618b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk private QSCustomizer mQSCustomizer; 628b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk private NotificationPanelView mPanelView; 63e5107a36b0547135791bfe2b692898994ef0887dJason Monk private boolean mListening; 648bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi 658bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi public QSContainer(Context context, AttributeSet attrs) { 668bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi super(context, attrs); 678bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi } 688bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi 698bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi @Override 708bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi protected void onFinishInflate() { 718bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi super.onFinishInflate(); 728bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi mQSPanel = (QSPanel) findViewById(R.id.quick_settings_panel); 73377e7ad8dc0562c6f445594288e451c377824e4cJason Monk mQSDetail = (QSDetail) findViewById(R.id.qs_detail); 74e1be342615db772ff11d369150349dbd874076f1Jason Monk mHeader = (BaseStatusBarHeader) findViewById(R.id.header); 75589bb70a77767980b6241ae676491edb42dedef5Jason Monk mQSDetail.setQsPanel(mQSPanel, mHeader); 76162011ebe8015f44d4d9ced519297a7cfb087af2Jason Monk mQSAnimator = new QSAnimator(this, (QuickQSPanel) mHeader.findViewById(R.id.quick_qs_panel), 77162011ebe8015f44d4d9ced519297a7cfb087af2Jason Monk mQSPanel); 788b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk mQSCustomizer = (QSCustomizer) findViewById(R.id.qs_customize); 798b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk mQSCustomizer.setQsContainer(this); 80162011ebe8015f44d4d9ced519297a7cfb087af2Jason Monk } 81162011ebe8015f44d4d9ced519297a7cfb087af2Jason Monk 8251fb85a088ac0c6797d18fed8317d709143b9757Jason Monk @Override 8351fb85a088ac0c6797d18fed8317d709143b9757Jason Monk public void onRtlPropertiesChanged(int layoutDirection) { 8451fb85a088ac0c6797d18fed8317d709143b9757Jason Monk super.onRtlPropertiesChanged(layoutDirection); 8551fb85a088ac0c6797d18fed8317d709143b9757Jason Monk mQSAnimator.onRtlChanged(); 8651fb85a088ac0c6797d18fed8317d709143b9757Jason Monk } 8751fb85a088ac0c6797d18fed8317d709143b9757Jason Monk 88162011ebe8015f44d4d9ced519297a7cfb087af2Jason Monk public void setHost(QSTileHost qsh) { 898b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk mQSPanel.setHost(qsh, mQSCustomizer); 90162011ebe8015f44d4d9ced519297a7cfb087af2Jason Monk mHeader.setQSPanel(mQSPanel); 91162011ebe8015f44d4d9ced519297a7cfb087af2Jason Monk mQSDetail.setHost(qsh); 92162011ebe8015f44d4d9ced519297a7cfb087af2Jason Monk mQSAnimator.setHost(qsh); 938bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi } 948bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi 958b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk public void setPanelView(NotificationPanelView panelView) { 968b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk mPanelView = panelView; 978b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk } 988b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk 998bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi @Override 10083e431fc51fc070901bee85970a5c4bf51f853acJason Monk protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 10183e431fc51fc070901bee85970a5c4bf51f853acJason Monk // Since we control our own bottom, be whatever size we want. 10283e431fc51fc070901bee85970a5c4bf51f853acJason Monk // Otherwise the QSPanel ends up with 0 height when the window is only the 10383e431fc51fc070901bee85970a5c4bf51f853acJason Monk // size of the status bar. 1046573ef20790b0438cfd60c6306e58db0ef85c31bJason Monk mQSPanel.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec( 1056573ef20790b0438cfd60c6306e58db0ef85c31bJason Monk MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.UNSPECIFIED)); 1066573ef20790b0438cfd60c6306e58db0ef85c31bJason Monk int width = mQSPanel.getMeasuredWidth(); 1076573ef20790b0438cfd60c6306e58db0ef85c31bJason Monk int height = ((LayoutParams) mQSPanel.getLayoutParams()).topMargin 1086573ef20790b0438cfd60c6306e58db0ef85c31bJason Monk + mQSPanel.getMeasuredHeight(); 1096573ef20790b0438cfd60c6306e58db0ef85c31bJason Monk super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), 1106573ef20790b0438cfd60c6306e58db0ef85c31bJason Monk MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); 1118b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk 1128b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk // QSCustomizer is always be the height of the screen, but do this after 1138b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk // other measuring to avoid changing the height of the QSContainer. 1148b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk getDisplay().getRealSize(mSizePoint); 1158b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk mQSCustomizer.measure(widthMeasureSpec, 1168b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk MeasureSpec.makeMeasureSpec(mSizePoint.y, MeasureSpec.EXACTLY)); 11783e431fc51fc070901bee85970a5c4bf51f853acJason Monk } 11883e431fc51fc070901bee85970a5c4bf51f853acJason Monk 11983e431fc51fc070901bee85970a5c4bf51f853acJason Monk @Override 1208bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 1218bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi super.onLayout(changed, left, top, right, bottom); 1228bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi updateBottom(); 1238bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi } 1248bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi 1258b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk public boolean isCustomizing() { 1268b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk return mQSCustomizer.isCustomizing(); 1278b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk } 1288b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk 1298bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi /** 1308bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi * Overrides the height of this view (post-layout), so that the content is clipped to that 1318bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi * height and the background is set to that height. 1328bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi * 1338bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi * @param heightOverride the overridden height 1348bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi */ 1358bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi public void setHeightOverride(int heightOverride) { 1368bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi mHeightOverride = heightOverride; 1378bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi updateBottom(); 1388bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi } 1398bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi 1408bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi /** 1418bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi * The height this view wants to be. This is different from {@link #getMeasuredHeight} such that 1428bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi * during closing the detail panel, this already returns the smaller height. 1438bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi */ 1448bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi public int getDesiredHeight() { 1458b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk if (isCustomizing()) { 1468b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk return getHeight(); 1478b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk } 148377e7ad8dc0562c6f445594288e451c377824e4cJason Monk if (mQSDetail.isClosingDetail()) { 149dfb851c6cf02ae4f52be116a3cac4f8c9795e1f2Jason Monk int panelHeight = ((LayoutParams) mQSPanel.getLayoutParams()).topMargin 150dfb851c6cf02ae4f52be116a3cac4f8c9795e1f2Jason Monk + mQSPanel.getMeasuredHeight(); 151dfb851c6cf02ae4f52be116a3cac4f8c9795e1f2Jason Monk return panelHeight + getPaddingBottom(); 1528bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi } else { 1538bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi return getMeasuredHeight(); 1548bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi } 1558bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi } 1568bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi 1578b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk public void notifyCustomizeChanged() { 1588b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk // The customize state changed, so our height changed. 1598b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk updateBottom(); 16039c98e652fd3e0e3ea3a334d60ba6ee979985978Jason Monk mQSPanel.setVisibility(!mQSCustomizer.isCustomizing() ? View.VISIBLE : View.INVISIBLE); 16139c98e652fd3e0e3ea3a334d60ba6ee979985978Jason Monk mHeader.setVisibility(!mQSCustomizer.isCustomizing() ? View.VISIBLE : View.INVISIBLE); 1628b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk // Let the panel know the position changed and it needs to update where notifications 1638b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk // and whatnot are. 1648b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk mPanelView.onQsHeightChanged(); 1658b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk } 1668b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk 1678bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi private void updateBottom() { 1684fe4a409bca01e16c807f3f76633afc1d9797e2aMuyuan Li int height = calculateContainerHeight(); 1694fe4a409bca01e16c807f3f76633afc1d9797e2aMuyuan Li setBottom(getTop() + height); 1704fe4a409bca01e16c807f3f76633afc1d9797e2aMuyuan Li mQSDetail.setBottom(getTop() + height); 1714fe4a409bca01e16c807f3f76633afc1d9797e2aMuyuan Li } 1724fe4a409bca01e16c807f3f76633afc1d9797e2aMuyuan Li 1734fe4a409bca01e16c807f3f76633afc1d9797e2aMuyuan Li protected int calculateContainerHeight() { 174e1be342615db772ff11d369150349dbd874076f1Jason Monk int heightOverride = mHeightOverride != -1 ? mHeightOverride : getMeasuredHeight(); 1754fe4a409bca01e16c807f3f76633afc1d9797e2aMuyuan Li return mQSCustomizer.isCustomizing() ? mQSCustomizer.getHeight() 1768b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk : (int) (mQsExpansion * (heightOverride - mHeader.getCollapsedHeight())) 177e1be342615db772ff11d369150349dbd874076f1Jason Monk + mHeader.getCollapsedHeight(); 1788bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi } 179e1be342615db772ff11d369150349dbd874076f1Jason Monk 180e1be342615db772ff11d369150349dbd874076f1Jason Monk private void updateQsState() { 181e1be342615db772ff11d369150349dbd874076f1Jason Monk boolean expandVisually = mQsExpanded || mStackScrollerOverscrolling || mHeaderAnimating; 182e1be342615db772ff11d369150349dbd874076f1Jason Monk mQSPanel.setExpanded(mQsExpanded); 18366448936dc7cb981effb5a741caa080278bcd6efXiaohui Chen mQSDetail.setExpanded(mQsExpanded); 184e1be342615db772ff11d369150349dbd874076f1Jason Monk mHeader.setVisibility((mQsExpanded || !mKeyguardShowing || mHeaderAnimating) 185e1be342615db772ff11d369150349dbd874076f1Jason Monk ? View.VISIBLE 186e1be342615db772ff11d369150349dbd874076f1Jason Monk : View.INVISIBLE); 187e1be342615db772ff11d369150349dbd874076f1Jason Monk mHeader.setExpanded((mKeyguardShowing && !mHeaderAnimating) 188e1be342615db772ff11d369150349dbd874076f1Jason Monk || (mQsExpanded && !mStackScrollerOverscrolling)); 189e1be342615db772ff11d369150349dbd874076f1Jason Monk mQSPanel.setVisibility(expandVisually ? View.VISIBLE : View.INVISIBLE); 190e1be342615db772ff11d369150349dbd874076f1Jason Monk } 191e1be342615db772ff11d369150349dbd874076f1Jason Monk 192e1be342615db772ff11d369150349dbd874076f1Jason Monk public BaseStatusBarHeader getHeader() { 193e1be342615db772ff11d369150349dbd874076f1Jason Monk return mHeader; 194e1be342615db772ff11d369150349dbd874076f1Jason Monk } 195e1be342615db772ff11d369150349dbd874076f1Jason Monk 196e1be342615db772ff11d369150349dbd874076f1Jason Monk public QSPanel getQsPanel() { 197e1be342615db772ff11d369150349dbd874076f1Jason Monk return mQSPanel; 198e1be342615db772ff11d369150349dbd874076f1Jason Monk } 199e1be342615db772ff11d369150349dbd874076f1Jason Monk 2008b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk public QSCustomizer getCustomizer() { 2018b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk return mQSCustomizer; 2028b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk } 2038b9d67fb636a89fe6537e7affb9d01a75f263d93Jason Monk 204377e7ad8dc0562c6f445594288e451c377824e4cJason Monk public boolean isShowingDetail() { 205377e7ad8dc0562c6f445594288e451c377824e4cJason Monk return mQSPanel.isShowingCustomize() || mQSDetail.isShowingDetail(); 206377e7ad8dc0562c6f445594288e451c377824e4cJason Monk } 207377e7ad8dc0562c6f445594288e451c377824e4cJason Monk 208e1be342615db772ff11d369150349dbd874076f1Jason Monk public void setHeaderClickable(boolean clickable) { 209e1be342615db772ff11d369150349dbd874076f1Jason Monk if (DEBUG) Log.d(TAG, "setHeaderClickable " + clickable); 210e1be342615db772ff11d369150349dbd874076f1Jason Monk mHeader.setClickable(clickable); 211e1be342615db772ff11d369150349dbd874076f1Jason Monk } 212e1be342615db772ff11d369150349dbd874076f1Jason Monk 213e1be342615db772ff11d369150349dbd874076f1Jason Monk public void setExpanded(boolean expanded) { 214e1be342615db772ff11d369150349dbd874076f1Jason Monk if (DEBUG) Log.d(TAG, "setExpanded " + expanded); 215e1be342615db772ff11d369150349dbd874076f1Jason Monk mQsExpanded = expanded; 216e5107a36b0547135791bfe2b692898994ef0887dJason Monk mQSPanel.setListening(mListening && mQsExpanded); 217e1be342615db772ff11d369150349dbd874076f1Jason Monk updateQsState(); 218e1be342615db772ff11d369150349dbd874076f1Jason Monk } 219e1be342615db772ff11d369150349dbd874076f1Jason Monk 220e1be342615db772ff11d369150349dbd874076f1Jason Monk public void setKeyguardShowing(boolean keyguardShowing) { 221e1be342615db772ff11d369150349dbd874076f1Jason Monk if (DEBUG) Log.d(TAG, "setKeyguardShowing " + keyguardShowing); 222e1be342615db772ff11d369150349dbd874076f1Jason Monk mKeyguardShowing = keyguardShowing; 2238fb7787cf9628284c75d873850a41b660b568348Jason Monk mQSAnimator.setOnKeyguard(keyguardShowing); 224e1be342615db772ff11d369150349dbd874076f1Jason Monk updateQsState(); 225e1be342615db772ff11d369150349dbd874076f1Jason Monk } 226e1be342615db772ff11d369150349dbd874076f1Jason Monk 227e1be342615db772ff11d369150349dbd874076f1Jason Monk public void setOverscrolling(boolean stackScrollerOverscrolling) { 228e1be342615db772ff11d369150349dbd874076f1Jason Monk if (DEBUG) Log.d(TAG, "setOverscrolling " + stackScrollerOverscrolling); 229e1be342615db772ff11d369150349dbd874076f1Jason Monk mStackScrollerOverscrolling = stackScrollerOverscrolling; 230e1be342615db772ff11d369150349dbd874076f1Jason Monk updateQsState(); 231e1be342615db772ff11d369150349dbd874076f1Jason Monk } 232e1be342615db772ff11d369150349dbd874076f1Jason Monk 233e1be342615db772ff11d369150349dbd874076f1Jason Monk public void setListening(boolean listening) { 234e1be342615db772ff11d369150349dbd874076f1Jason Monk if (DEBUG) Log.d(TAG, "setListening " + listening); 235e5107a36b0547135791bfe2b692898994ef0887dJason Monk mListening = listening; 236e1be342615db772ff11d369150349dbd874076f1Jason Monk mHeader.setListening(listening); 237e5107a36b0547135791bfe2b692898994ef0887dJason Monk mQSPanel.setListening(mListening && mQsExpanded); 238e1be342615db772ff11d369150349dbd874076f1Jason Monk } 239e1be342615db772ff11d369150349dbd874076f1Jason Monk 240b5ece9a9d6add01b7a0c392372ff8ba061fcb7e7Jason Monk public void setHeaderListening(boolean listening) { 241b5ece9a9d6add01b7a0c392372ff8ba061fcb7e7Jason Monk mHeader.setListening(listening); 242b5ece9a9d6add01b7a0c392372ff8ba061fcb7e7Jason Monk } 243b5ece9a9d6add01b7a0c392372ff8ba061fcb7e7Jason Monk 244e1be342615db772ff11d369150349dbd874076f1Jason Monk public void setQsExpansion(float expansion, float headerTranslation) { 245e1be342615db772ff11d369150349dbd874076f1Jason Monk if (DEBUG) Log.d(TAG, "setQSExpansion " + expansion + " " + headerTranslation); 246e1be342615db772ff11d369150349dbd874076f1Jason Monk mQsExpansion = expansion; 247e1be342615db772ff11d369150349dbd874076f1Jason Monk final float translationScaleY = expansion - 1; 248e1be342615db772ff11d369150349dbd874076f1Jason Monk if (!mHeaderAnimating) { 249e1be342615db772ff11d369150349dbd874076f1Jason Monk setTranslationY(mKeyguardShowing ? (translationScaleY * mHeader.getHeight()) 250e1be342615db772ff11d369150349dbd874076f1Jason Monk : headerTranslation); 251e1be342615db772ff11d369150349dbd874076f1Jason Monk } 252e1be342615db772ff11d369150349dbd874076f1Jason Monk mHeader.setExpansion(mKeyguardShowing ? 1 : expansion); 253e1be342615db772ff11d369150349dbd874076f1Jason Monk mQSPanel.setTranslationY(translationScaleY * mQSPanel.getHeight()); 254377e7ad8dc0562c6f445594288e451c377824e4cJason Monk mQSDetail.setFullyExpanded(expansion == 1); 255162011ebe8015f44d4d9ced519297a7cfb087af2Jason Monk mQSAnimator.setPosition(expansion); 256e1be342615db772ff11d369150349dbd874076f1Jason Monk updateBottom(); 257f7d9c49223c4f2fd8a498160914d41801e6b10eaJason Monk 258f7d9c49223c4f2fd8a498160914d41801e6b10eaJason Monk // Set bounds on the QS panel so it doesn't run over the header. 259f7d9c49223c4f2fd8a498160914d41801e6b10eaJason Monk mQsBounds.top = (int) (mQSPanel.getHeight() * (1 - expansion)); 260f7d9c49223c4f2fd8a498160914d41801e6b10eaJason Monk mQsBounds.right = mQSPanel.getWidth(); 261f7d9c49223c4f2fd8a498160914d41801e6b10eaJason Monk mQsBounds.bottom = mQSPanel.getHeight(); 262f7d9c49223c4f2fd8a498160914d41801e6b10eaJason Monk mQSPanel.setClipBounds(mQsBounds); 263e1be342615db772ff11d369150349dbd874076f1Jason Monk } 264e1be342615db772ff11d369150349dbd874076f1Jason Monk 265e1be342615db772ff11d369150349dbd874076f1Jason Monk public void animateHeaderSlidingIn(long delay) { 266e1be342615db772ff11d369150349dbd874076f1Jason Monk if (DEBUG) Log.d(TAG, "animateHeaderSlidingIn"); 267e1be342615db772ff11d369150349dbd874076f1Jason Monk // If the QS is already expanded we don't need to slide in the header as it's already 268e1be342615db772ff11d369150349dbd874076f1Jason Monk // visible. 269e1be342615db772ff11d369150349dbd874076f1Jason Monk if (!mQsExpanded) { 270e1be342615db772ff11d369150349dbd874076f1Jason Monk mHeaderAnimating = true; 271e1be342615db772ff11d369150349dbd874076f1Jason Monk mDelay = delay; 272e1be342615db772ff11d369150349dbd874076f1Jason Monk getViewTreeObserver().addOnPreDrawListener(mStartHeaderSlidingIn); 273e1be342615db772ff11d369150349dbd874076f1Jason Monk } 274e1be342615db772ff11d369150349dbd874076f1Jason Monk } 275e1be342615db772ff11d369150349dbd874076f1Jason Monk 276e1be342615db772ff11d369150349dbd874076f1Jason Monk public void animateHeaderSlidingOut() { 277e1be342615db772ff11d369150349dbd874076f1Jason Monk if (DEBUG) Log.d(TAG, "animateHeaderSlidingOut"); 278e1be342615db772ff11d369150349dbd874076f1Jason Monk mHeaderAnimating = true; 279e1be342615db772ff11d369150349dbd874076f1Jason Monk animate().y(-mHeader.getHeight()) 280e1be342615db772ff11d369150349dbd874076f1Jason Monk .setStartDelay(0) 281e1be342615db772ff11d369150349dbd874076f1Jason Monk .setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD) 282e1be342615db772ff11d369150349dbd874076f1Jason Monk .setInterpolator(Interpolators.FAST_OUT_SLOW_IN) 283e1be342615db772ff11d369150349dbd874076f1Jason Monk .setListener(new AnimatorListenerAdapter() { 284e1be342615db772ff11d369150349dbd874076f1Jason Monk @Override 285e1be342615db772ff11d369150349dbd874076f1Jason Monk public void onAnimationEnd(Animator animation) { 286e1be342615db772ff11d369150349dbd874076f1Jason Monk animate().setListener(null); 287e1be342615db772ff11d369150349dbd874076f1Jason Monk mHeaderAnimating = false; 288e1be342615db772ff11d369150349dbd874076f1Jason Monk updateQsState(); 289e1be342615db772ff11d369150349dbd874076f1Jason Monk } 290e1be342615db772ff11d369150349dbd874076f1Jason Monk }) 291e1be342615db772ff11d369150349dbd874076f1Jason Monk .start(); 292e1be342615db772ff11d369150349dbd874076f1Jason Monk } 293e1be342615db772ff11d369150349dbd874076f1Jason Monk 294e1be342615db772ff11d369150349dbd874076f1Jason Monk private final ViewTreeObserver.OnPreDrawListener mStartHeaderSlidingIn 295e1be342615db772ff11d369150349dbd874076f1Jason Monk = new ViewTreeObserver.OnPreDrawListener() { 296e1be342615db772ff11d369150349dbd874076f1Jason Monk @Override 297e1be342615db772ff11d369150349dbd874076f1Jason Monk public boolean onPreDraw() { 298e1be342615db772ff11d369150349dbd874076f1Jason Monk getViewTreeObserver().removeOnPreDrawListener(this); 299e1be342615db772ff11d369150349dbd874076f1Jason Monk animate() 300e1be342615db772ff11d369150349dbd874076f1Jason Monk .translationY(0f) 301e1be342615db772ff11d369150349dbd874076f1Jason Monk .setStartDelay(mDelay) 302e1be342615db772ff11d369150349dbd874076f1Jason Monk .setDuration(StackStateAnimator.ANIMATION_DURATION_GO_TO_FULL_SHADE) 303e1be342615db772ff11d369150349dbd874076f1Jason Monk .setInterpolator(Interpolators.FAST_OUT_SLOW_IN) 304e1be342615db772ff11d369150349dbd874076f1Jason Monk .setListener(mAnimateHeaderSlidingInListener) 305e1be342615db772ff11d369150349dbd874076f1Jason Monk .start(); 306e1be342615db772ff11d369150349dbd874076f1Jason Monk setY(-mHeader.getHeight()); 307e1be342615db772ff11d369150349dbd874076f1Jason Monk return true; 308e1be342615db772ff11d369150349dbd874076f1Jason Monk } 309e1be342615db772ff11d369150349dbd874076f1Jason Monk }; 310e1be342615db772ff11d369150349dbd874076f1Jason Monk 311e1be342615db772ff11d369150349dbd874076f1Jason Monk private final Animator.AnimatorListener mAnimateHeaderSlidingInListener 312e1be342615db772ff11d369150349dbd874076f1Jason Monk = new AnimatorListenerAdapter() { 313e1be342615db772ff11d369150349dbd874076f1Jason Monk @Override 314e1be342615db772ff11d369150349dbd874076f1Jason Monk public void onAnimationEnd(Animator animation) { 315e1be342615db772ff11d369150349dbd874076f1Jason Monk mHeaderAnimating = false; 316e1be342615db772ff11d369150349dbd874076f1Jason Monk updateQsState(); 317e1be342615db772ff11d369150349dbd874076f1Jason Monk } 318e1be342615db772ff11d369150349dbd874076f1Jason Monk }; 3194fe4a409bca01e16c807f3f76633afc1d9797e2aMuyuan Li 3204fe4a409bca01e16c807f3f76633afc1d9797e2aMuyuan Li public int getQsMinExpansionHeight() { 3214fe4a409bca01e16c807f3f76633afc1d9797e2aMuyuan Li return mHeader.getHeight(); 3224fe4a409bca01e16c807f3f76633afc1d9797e2aMuyuan Li } 3235f2ca6b1a1f739583e4ea9f3d3dfd22931d793e0Selim Cinek 3245f2ca6b1a1f739583e4ea9f3d3dfd22931d793e0Selim Cinek public void hideImmediately() { 3255f2ca6b1a1f739583e4ea9f3d3dfd22931d793e0Selim Cinek animate().cancel(); 3265f2ca6b1a1f739583e4ea9f3d3dfd22931d793e0Selim Cinek setY(-mHeader.getHeight()); 3275f2ca6b1a1f739583e4ea9f3d3dfd22931d793e0Selim Cinek } 3288bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi} 329