Improve transition when going to Wifi/BT detail panel
Animate the height change of the lower QS panel when going into Wifi/BT or any other panel which is higher than the default size. Bug: 18665311 Change-Id: Ic1d1f19183cf6b502d6b623388b315ed6e0a3c9f
This commit is contained in:
@@ -13,7 +13,7 @@
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<FrameLayout
|
||||
<com.android.systemui.qs.QSContainer
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/quick_settings_container"
|
||||
android:layout_width="match_parent"
|
||||
@@ -28,4 +28,4 @@
|
||||
android:background="#0000"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
</FrameLayout>
|
||||
</com.android.systemui.qs.QSContainer>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -67,8 +67,10 @@ public class QSPanel extends ViewGroup {
|
||||
private int mPanelPaddingBottom;
|
||||
private int mDualTileUnderlap;
|
||||
private int mBrightnessPaddingTop;
|
||||
private int mGridHeight;
|
||||
private boolean mExpanded;
|
||||
private boolean mListening;
|
||||
private boolean mClosingDetail;
|
||||
|
||||
private Record mDetailRecord;
|
||||
private Callback mCallback;
|
||||
@@ -320,6 +322,14 @@ public class QSPanel extends ViewGroup {
|
||||
showDetail(false, mDetailRecord);
|
||||
}
|
||||
|
||||
public boolean isClosingDetail() {
|
||||
return mClosingDetail;
|
||||
}
|
||||
|
||||
public int getGridHeight() {
|
||||
return mGridHeight;
|
||||
}
|
||||
|
||||
private void handleShowDetail(Record r, boolean show) {
|
||||
if (r instanceof TileRecord) {
|
||||
handleShowDetailTile((TileRecord) r, show);
|
||||
@@ -364,6 +374,7 @@ public class QSPanel extends ViewGroup {
|
||||
setDetailRecord(r);
|
||||
listener = mHideGridContentWhenDone;
|
||||
} else {
|
||||
mClosingDetail = true;
|
||||
setGridContentVisibility(true);
|
||||
listener = mTeardownDetailWhenDone;
|
||||
fireScanStateChanged(false);
|
||||
@@ -426,6 +437,7 @@ public class QSPanel extends ViewGroup {
|
||||
if (mDetail.getMeasuredHeight() < h) {
|
||||
mDetail.measure(exactly(width), exactly(h));
|
||||
}
|
||||
mGridHeight = h;
|
||||
setMeasuredDimension(width, Math.max(h, mDetail.getMeasuredHeight()));
|
||||
}
|
||||
|
||||
@@ -537,6 +549,7 @@ public class QSPanel extends ViewGroup {
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mDetailContent.removeAllViews();
|
||||
setDetailRecord(null);
|
||||
mClosingDetail = false;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ import android.widget.TextView;
|
||||
|
||||
import com.android.keyguard.KeyguardStatusView;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.qs.QSContainer;
|
||||
import com.android.systemui.qs.QSPanel;
|
||||
import com.android.systemui.statusbar.ExpandableView;
|
||||
import com.android.systemui.statusbar.FlingAnimationUtils;
|
||||
@@ -71,7 +72,7 @@ public class NotificationPanelView extends PanelView implements
|
||||
private StatusBarHeaderView mHeader;
|
||||
private KeyguardUserSwitcher mKeyguardUserSwitcher;
|
||||
private KeyguardStatusBarView mKeyguardStatusBar;
|
||||
private View mQsContainer;
|
||||
private QSContainer mQsContainer;
|
||||
private QSPanel mQsPanel;
|
||||
private KeyguardStatusView mKeyguardStatusView;
|
||||
private ObservableScrollView mScrollView;
|
||||
@@ -161,6 +162,7 @@ public class NotificationPanelView extends PanelView implements
|
||||
private boolean mKeyguardStatusViewAnimating;
|
||||
private boolean mHeaderAnimatingIn;
|
||||
private ObjectAnimator mQsContainerAnimator;
|
||||
private ValueAnimator mQsSizeChangeAnimator;
|
||||
|
||||
private boolean mShadeEmpty;
|
||||
|
||||
@@ -188,7 +190,7 @@ public class NotificationPanelView extends PanelView implements
|
||||
mHeader.setOnClickListener(this);
|
||||
mKeyguardStatusBar = (KeyguardStatusBarView) findViewById(R.id.keyguard_header);
|
||||
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);
|
||||
mClockView = (TextView) findViewById(R.id.clock_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());
|
||||
|
||||
// Calculate quick setting heights.
|
||||
int oldMaxHeight = mQsMaxExpansionHeight;
|
||||
mQsMinExpansionHeight = mKeyguardShowing ? 0 : mHeader.getCollapsedHeight() + mQsPeekHeight;
|
||||
mQsMaxExpansionHeight = mHeader.getExpandedHeight() + mQsContainer.getHeight();
|
||||
mQsMaxExpansionHeight = mHeader.getExpandedHeight() + mQsContainer.getDesiredHeight();
|
||||
positionClockAndNotifications();
|
||||
if (mQsExpanded) {
|
||||
if (mQsFullyExpanded) {
|
||||
mQsExpansionHeight = mQsMaxExpansionHeight;
|
||||
requestScrollerTopPaddingUpdate(false /* animate */);
|
||||
if (mQsExpanded && mQsFullyExpanded) {
|
||||
mQsExpansionHeight = mQsMaxExpansionHeight;
|
||||
requestScrollerTopPaddingUpdate(false /* animate */);
|
||||
requestPanelHeightUpdate();
|
||||
|
||||
// Size has changed, start an animation.
|
||||
if (mQsMaxExpansionHeight != oldMaxHeight) {
|
||||
startQsSizeChangeAnimation(oldMaxHeight, mQsMaxExpansionHeight);
|
||||
}
|
||||
} else {
|
||||
} else if (!mQsExpanded) {
|
||||
setQsExpansion(mQsMinExpansionHeight + mLastOverscroll);
|
||||
mNotificationStackScroller.setStackHeight(getExpandedHeight());
|
||||
}
|
||||
mNotificationStackScroller.setStackHeight(getExpandedHeight());
|
||||
updateHeader();
|
||||
mNotificationStackScroller.updateIsSmallScreen(
|
||||
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
|
||||
@@ -310,6 +326,32 @@ public class NotificationPanelView extends PanelView implements
|
||||
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
|
||||
* showing.
|
||||
@@ -1113,7 +1155,7 @@ public class NotificationPanelView extends PanelView implements
|
||||
|
||||
private void setQsTranslation(float height) {
|
||||
if (!mHeaderAnimatingIn) {
|
||||
mQsContainer.setY(height - mQsContainer.getHeight() + getHeaderTranslation());
|
||||
mQsContainer.setY(height - mQsContainer.getDesiredHeight() + getHeaderTranslation());
|
||||
}
|
||||
if (mKeyguardShowing) {
|
||||
mHeader.setY(interpolate(getQsExpansionFraction(), -mHeader.getHeight(), 0));
|
||||
@@ -1137,6 +1179,8 @@ public class NotificationPanelView extends PanelView implements
|
||||
: maxQs;
|
||||
return (int) interpolate(getExpandedFraction(),
|
||||
mQsMinExpansionHeight, max);
|
||||
} else if (mQsSizeChangeAnimator != null) {
|
||||
return (int) mQsSizeChangeAnimator.getAnimatedValue();
|
||||
} else if (mKeyguardShowing && mScrollYOverride == -1) {
|
||||
|
||||
// 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.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(
|
||||
mQsMaxExpansionHeight + mNotificationStackScroller.getNotificationTopPadding(),
|
||||
maxQsHeight + mNotificationStackScroller.getNotificationTopPadding(),
|
||||
mStatusBarState == StatusBarState.KEYGUARD
|
||||
? mClockPositionResult.stackScrollerPadding - mTopPaddingAdjustment
|
||||
: 0)
|
||||
+ notificationHeight;
|
||||
if (totalHeight > mNotificationStackScroller.getHeight()) {
|
||||
float fullyCollapsedHeight = mQsMaxExpansionHeight
|
||||
float fullyCollapsedHeight = maxQsHeight
|
||||
+ mNotificationStackScroller.getMinStackHeight()
|
||||
+ mNotificationStackScroller.getNotificationTopPadding()
|
||||
- getScrollViewScrollY();
|
||||
|
||||
Reference in New Issue
Block a user