am ab60f285: Merge "Improve transition when going to Wifi/BT detail panel" into lmp-mr1-dev

* commit 'ab60f2855b0d2a96fe1610f42a83dc761c4c10e6':
  Improve transition when going to Wifi/BT detail panel
This commit is contained in:
Jorim Jaggi
2014-12-12 15:39:16 +00:00
committed by Android Git Automerger
4 changed files with 153 additions and 14 deletions

View File

@@ -13,7 +13,7 @@
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
--> -->
<FrameLayout <com.android.systemui.qs.QSContainer
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/quick_settings_container" android:id="@+id/quick_settings_container"
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -28,4 +28,4 @@
android:background="#0000" android:background="#0000"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" /> android:layout_height="wrap_content" />
</FrameLayout> </com.android.systemui.qs.QSContainer>

View File

@@ -0,0 +1,76 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.systemui.qs;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.FrameLayout;
import com.android.systemui.R;
/**
* Wrapper view with background which contains {@link QSPanel}
*/
public class QSContainer extends FrameLayout {
private int mHeightOverride = -1;
private QSPanel mQSPanel;
public QSContainer(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mQSPanel = (QSPanel) findViewById(R.id.quick_settings_panel);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
updateBottom();
}
/**
* Overrides the height of this view (post-layout), so that the content is clipped to that
* height and the background is set to that height.
*
* @param heightOverride the overridden height
*/
public void setHeightOverride(int heightOverride) {
mHeightOverride = heightOverride;
updateBottom();
}
/**
* The height this view wants to be. This is different from {@link #getMeasuredHeight} such that
* during closing the detail panel, this already returns the smaller height.
*/
public int getDesiredHeight() {
if (mQSPanel.isClosingDetail()) {
return mQSPanel.getGridHeight() + getPaddingTop() + getPaddingBottom();
} else {
return getMeasuredHeight();
}
}
private void updateBottom() {
int height = mHeightOverride != -1 ? mHeightOverride : getMeasuredHeight();
setBottom(getTop() + height);
}
}

View File

@@ -67,8 +67,10 @@ public class QSPanel extends ViewGroup {
private int mPanelPaddingBottom; private int mPanelPaddingBottom;
private int mDualTileUnderlap; private int mDualTileUnderlap;
private int mBrightnessPaddingTop; private int mBrightnessPaddingTop;
private int mGridHeight;
private boolean mExpanded; private boolean mExpanded;
private boolean mListening; private boolean mListening;
private boolean mClosingDetail;
private Record mDetailRecord; private Record mDetailRecord;
private Callback mCallback; private Callback mCallback;
@@ -320,6 +322,14 @@ public class QSPanel extends ViewGroup {
showDetail(false, mDetailRecord); showDetail(false, mDetailRecord);
} }
public boolean isClosingDetail() {
return mClosingDetail;
}
public int getGridHeight() {
return mGridHeight;
}
private void handleShowDetail(Record r, boolean show) { private void handleShowDetail(Record r, boolean show) {
if (r instanceof TileRecord) { if (r instanceof TileRecord) {
handleShowDetailTile((TileRecord) r, show); handleShowDetailTile((TileRecord) r, show);
@@ -364,6 +374,7 @@ public class QSPanel extends ViewGroup {
setDetailRecord(r); setDetailRecord(r);
listener = mHideGridContentWhenDone; listener = mHideGridContentWhenDone;
} else { } else {
mClosingDetail = true;
setGridContentVisibility(true); setGridContentVisibility(true);
listener = mTeardownDetailWhenDone; listener = mTeardownDetailWhenDone;
fireScanStateChanged(false); fireScanStateChanged(false);
@@ -426,6 +437,7 @@ public class QSPanel extends ViewGroup {
if (mDetail.getMeasuredHeight() < h) { if (mDetail.getMeasuredHeight() < h) {
mDetail.measure(exactly(width), exactly(h)); mDetail.measure(exactly(width), exactly(h));
} }
mGridHeight = h;
setMeasuredDimension(width, Math.max(h, mDetail.getMeasuredHeight())); setMeasuredDimension(width, Math.max(h, mDetail.getMeasuredHeight()));
} }
@@ -537,6 +549,7 @@ public class QSPanel extends ViewGroup {
public void onAnimationEnd(Animator animation) { public void onAnimationEnd(Animator animation) {
mDetailContent.removeAllViews(); mDetailContent.removeAllViews();
setDetailRecord(null); setDetailRecord(null);
mClosingDetail = false;
}; };
}; };

View File

@@ -40,6 +40,7 @@ import android.widget.TextView;
import com.android.keyguard.KeyguardStatusView; import com.android.keyguard.KeyguardStatusView;
import com.android.systemui.R; import com.android.systemui.R;
import com.android.systemui.qs.QSContainer;
import com.android.systemui.qs.QSPanel; import com.android.systemui.qs.QSPanel;
import com.android.systemui.statusbar.ExpandableView; import com.android.systemui.statusbar.ExpandableView;
import com.android.systemui.statusbar.FlingAnimationUtils; import com.android.systemui.statusbar.FlingAnimationUtils;
@@ -71,7 +72,7 @@ public class NotificationPanelView extends PanelView implements
private StatusBarHeaderView mHeader; private StatusBarHeaderView mHeader;
private KeyguardUserSwitcher mKeyguardUserSwitcher; private KeyguardUserSwitcher mKeyguardUserSwitcher;
private KeyguardStatusBarView mKeyguardStatusBar; private KeyguardStatusBarView mKeyguardStatusBar;
private View mQsContainer; private QSContainer mQsContainer;
private QSPanel mQsPanel; private QSPanel mQsPanel;
private KeyguardStatusView mKeyguardStatusView; private KeyguardStatusView mKeyguardStatusView;
private ObservableScrollView mScrollView; private ObservableScrollView mScrollView;
@@ -161,6 +162,7 @@ public class NotificationPanelView extends PanelView implements
private boolean mKeyguardStatusViewAnimating; private boolean mKeyguardStatusViewAnimating;
private boolean mHeaderAnimatingIn; private boolean mHeaderAnimatingIn;
private ObjectAnimator mQsContainerAnimator; private ObjectAnimator mQsContainerAnimator;
private ValueAnimator mQsSizeChangeAnimator;
private boolean mShadeEmpty; private boolean mShadeEmpty;
@@ -188,7 +190,7 @@ public class NotificationPanelView extends PanelView implements
mHeader.setOnClickListener(this); mHeader.setOnClickListener(this);
mKeyguardStatusBar = (KeyguardStatusBarView) findViewById(R.id.keyguard_header); mKeyguardStatusBar = (KeyguardStatusBarView) findViewById(R.id.keyguard_header);
mKeyguardStatusView = (KeyguardStatusView) findViewById(R.id.keyguard_status_view); mKeyguardStatusView = (KeyguardStatusView) findViewById(R.id.keyguard_status_view);
mQsContainer = findViewById(R.id.quick_settings_container); mQsContainer = (QSContainer) findViewById(R.id.quick_settings_container);
mQsPanel = (QSPanel) findViewById(R.id.quick_settings_panel); mQsPanel = (QSPanel) findViewById(R.id.quick_settings_panel);
mClockView = (TextView) findViewById(R.id.clock_view); mClockView = (TextView) findViewById(R.id.clock_view);
mScrollView = (ObservableScrollView) findViewById(R.id.scroll_view); mScrollView = (ObservableScrollView) findViewById(R.id.scroll_view);
@@ -283,21 +285,35 @@ public class NotificationPanelView extends PanelView implements
mKeyguardStatusView.setPivotY((FONT_HEIGHT - CAP_HEIGHT) / 2048f * mClockView.getTextSize()); mKeyguardStatusView.setPivotY((FONT_HEIGHT - CAP_HEIGHT) / 2048f * mClockView.getTextSize());
// Calculate quick setting heights. // Calculate quick setting heights.
int oldMaxHeight = mQsMaxExpansionHeight;
mQsMinExpansionHeight = mKeyguardShowing ? 0 : mHeader.getCollapsedHeight() + mQsPeekHeight; mQsMinExpansionHeight = mKeyguardShowing ? 0 : mHeader.getCollapsedHeight() + mQsPeekHeight;
mQsMaxExpansionHeight = mHeader.getExpandedHeight() + mQsContainer.getHeight(); mQsMaxExpansionHeight = mHeader.getExpandedHeight() + mQsContainer.getDesiredHeight();
positionClockAndNotifications(); positionClockAndNotifications();
if (mQsExpanded) { if (mQsExpanded && mQsFullyExpanded) {
if (mQsFullyExpanded) { mQsExpansionHeight = mQsMaxExpansionHeight;
mQsExpansionHeight = mQsMaxExpansionHeight; requestScrollerTopPaddingUpdate(false /* animate */);
requestScrollerTopPaddingUpdate(false /* animate */); requestPanelHeightUpdate();
// Size has changed, start an animation.
if (mQsMaxExpansionHeight != oldMaxHeight) {
startQsSizeChangeAnimation(oldMaxHeight, mQsMaxExpansionHeight);
} }
} else { } else if (!mQsExpanded) {
setQsExpansion(mQsMinExpansionHeight + mLastOverscroll); setQsExpansion(mQsMinExpansionHeight + mLastOverscroll);
mNotificationStackScroller.setStackHeight(getExpandedHeight());
} }
mNotificationStackScroller.setStackHeight(getExpandedHeight());
updateHeader(); updateHeader();
mNotificationStackScroller.updateIsSmallScreen( mNotificationStackScroller.updateIsSmallScreen(
mHeader.getCollapsedHeight() + mQsPeekHeight); mHeader.getCollapsedHeight() + mQsPeekHeight);
// If we are running a size change animation, the animation takes care of the height of
// the container. However, if we are not animating, we always need to make the QS container
// the desired height so when closing the QS detail, it stays smaller after the size change
// animation is finished but the detail view is still being animated away (this animation
// takes longer than the size change animation).
if (mQsSizeChangeAnimator == null) {
mQsContainer.setHeightOverride(mQsContainer.getDesiredHeight());
}
} }
@Override @Override
@@ -310,6 +326,32 @@ public class NotificationPanelView extends PanelView implements
mSecureCameraLaunchManager.destroy(); mSecureCameraLaunchManager.destroy();
} }
private void startQsSizeChangeAnimation(int oldHeight, final int newHeight) {
if (mQsSizeChangeAnimator != null) {
oldHeight = (int) mQsSizeChangeAnimator.getAnimatedValue();
mQsSizeChangeAnimator.cancel();
}
mQsSizeChangeAnimator = ValueAnimator.ofInt(oldHeight, newHeight);
mQsSizeChangeAnimator.setDuration(300);
mQsSizeChangeAnimator.setInterpolator(mFastOutSlowInInterpolator);
mQsSizeChangeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
requestScrollerTopPaddingUpdate(false /* animate */);
requestPanelHeightUpdate();
int height = (int) mQsSizeChangeAnimator.getAnimatedValue();
mQsContainer.setHeightOverride(height - mHeader.getExpandedHeight());
}
});
mQsSizeChangeAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mQsSizeChangeAnimator = null;
}
});
mQsSizeChangeAnimator.start();
}
/** /**
* Positions the clock and notifications dynamically depending on how many notifications are * Positions the clock and notifications dynamically depending on how many notifications are
* showing. * showing.
@@ -1113,7 +1155,7 @@ public class NotificationPanelView extends PanelView implements
private void setQsTranslation(float height) { private void setQsTranslation(float height) {
if (!mHeaderAnimatingIn) { if (!mHeaderAnimatingIn) {
mQsContainer.setY(height - mQsContainer.getHeight() + getHeaderTranslation()); mQsContainer.setY(height - mQsContainer.getDesiredHeight() + getHeaderTranslation());
} }
if (mKeyguardShowing) { if (mKeyguardShowing) {
mHeader.setY(interpolate(getQsExpansionFraction(), -mHeader.getHeight(), 0)); mHeader.setY(interpolate(getQsExpansionFraction(), -mHeader.getHeight(), 0));
@@ -1137,6 +1179,8 @@ public class NotificationPanelView extends PanelView implements
: maxQs; : maxQs;
return (int) interpolate(getExpandedFraction(), return (int) interpolate(getExpandedFraction(),
mQsMinExpansionHeight, max); mQsMinExpansionHeight, max);
} else if (mQsSizeChangeAnimator != null) {
return (int) mQsSizeChangeAnimator.getAnimatedValue();
} else if (mKeyguardShowing && mScrollYOverride == -1) { } else if (mKeyguardShowing && mScrollYOverride == -1) {
// We can only do the smoother transition on Keyguard when we also are not collapsing // We can only do the smoother transition on Keyguard when we also are not collapsing
@@ -1348,14 +1392,20 @@ public class NotificationPanelView extends PanelView implements
+ mNotificationStackScroller.getBottomStackPeekSize() + mNotificationStackScroller.getBottomStackPeekSize()
+ mNotificationStackScroller.getCollapseSecondCardPadding(); + mNotificationStackScroller.getCollapseSecondCardPadding();
} }
int maxQsHeight = mQsMaxExpansionHeight;
// If an animation is changing the size of the QS panel, take the animated value.
if (mQsSizeChangeAnimator != null) {
maxQsHeight = (int) mQsSizeChangeAnimator.getAnimatedValue();
}
float totalHeight = Math.max( float totalHeight = Math.max(
mQsMaxExpansionHeight + mNotificationStackScroller.getNotificationTopPadding(), maxQsHeight + mNotificationStackScroller.getNotificationTopPadding(),
mStatusBarState == StatusBarState.KEYGUARD mStatusBarState == StatusBarState.KEYGUARD
? mClockPositionResult.stackScrollerPadding - mTopPaddingAdjustment ? mClockPositionResult.stackScrollerPadding - mTopPaddingAdjustment
: 0) : 0)
+ notificationHeight; + notificationHeight;
if (totalHeight > mNotificationStackScroller.getHeight()) { if (totalHeight > mNotificationStackScroller.getHeight()) {
float fullyCollapsedHeight = mQsMaxExpansionHeight float fullyCollapsedHeight = maxQsHeight
+ mNotificationStackScroller.getMinStackHeight() + mNotificationStackScroller.getMinStackHeight()
+ mNotificationStackScroller.getNotificationTopPadding() + mNotificationStackScroller.getNotificationTopPadding()
- getScrollViewScrollY(); - getScrollViewScrollY();