Move QS Edit into QSContainer
This will let it play nicely with heads up.
- Move to QS Container.
- QS Edit is always full height (some layout hacks to do this)
- Always draw QS customizer on top when animating
- Block all panel scrolling while QS edit is open (all touches
go to editing)
- Instantaneously change the height of the QS container at
start/end of animation as needed
Bug: 26969293
Change-Id: Iedc6f5aaf659dcc6750972eae5f69cc0cd2df844
diff --git a/packages/SystemUI/res/layout/qs_customize_panel.xml b/packages/SystemUI/res/layout/qs_customize_panel.xml
index 582ad48..0491ea0 100644
--- a/packages/SystemUI/res/layout/qs_customize_panel.xml
+++ b/packages/SystemUI/res/layout/qs_customize_panel.xml
@@ -14,10 +14,12 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
+<!-- Height is 0 because it will be managed by the QSContainer manually -->
<com.android.systemui.qs.customize.QSCustomizer
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="match_parent"
+ android:layout_height="0dp"
android:orientation="vertical"
android:background="@drawable/qs_customizer_background"
android:gravity="center_horizontal">
diff --git a/packages/SystemUI/res/layout/qs_panel.xml b/packages/SystemUI/res/layout/qs_panel.xml
index 994d3c9..ef15195 100644
--- a/packages/SystemUI/res/layout/qs_panel.xml
+++ b/packages/SystemUI/res/layout/qs_panel.xml
@@ -34,4 +34,7 @@
<include android:id="@+id/qs_detail" layout="@layout/qs_detail" />
+ <include android:id="@+id/qs_customize" layout="@layout/qs_customize_panel"
+ android:visibility="gone" />
+
</com.android.systemui.qs.QSContainer>
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 656941f..ccefb5f 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -43,8 +43,10 @@
android:id="@+id/qs_density_container"
android:layout="@layout/qs_panel"
android:layout_width="@dimen/notification_panel_width"
- android:layout_height="wrap_content"
- android:layout_gravity="@integer/notification_panel_layout_gravity" />
+ android:layout_height="match_parent"
+ android:layout_gravity="@integer/notification_panel_layout_gravity"
+ android:clipToPadding="false"
+ android:clipChildren="false" />
<com.android.systemui.statusbar.stack.NotificationStackScrollLayout
android:id="@+id/notification_stack_scroller"
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
index c0c1e4d..5b05e84 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
@@ -19,6 +19,7 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
+import android.graphics.Point;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
@@ -26,7 +27,9 @@
import android.widget.FrameLayout;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
+import com.android.systemui.qs.customize.QSCustomizer;
import com.android.systemui.statusbar.phone.BaseStatusBarHeader;
+import com.android.systemui.statusbar.phone.NotificationPanelView;
import com.android.systemui.statusbar.phone.QSTileHost;
import com.android.systemui.statusbar.stack.StackStateAnimator;
@@ -39,6 +42,8 @@
private static final String TAG = "QSContainer";
private static final boolean DEBUG = false;
+ private final Point mSizePoint = new Point();
+
private int mHeightOverride = -1;
private QSPanel mQSPanel;
private QSDetail mQSDetail;
@@ -51,6 +56,8 @@
private long mDelay;
private QSAnimator mQSAnimator;
+ private QSCustomizer mQSCustomizer;
+ private NotificationPanelView mPanelView;
public QSContainer(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -65,21 +72,33 @@
mHeader = (BaseStatusBarHeader) findViewById(R.id.header);
mQSAnimator = new QSAnimator(this, (QuickQSPanel) mHeader.findViewById(R.id.quick_qs_panel),
mQSPanel);
+ mQSCustomizer = (QSCustomizer) findViewById(R.id.qs_customize);
+ mQSCustomizer.setQsContainer(this);
}
public void setHost(QSTileHost qsh) {
- mQSPanel.setHost(qsh);
+ mQSPanel.setHost(qsh, mQSCustomizer);
mHeader.setQSPanel(mQSPanel);
mQSDetail.setHost(qsh);
mQSAnimator.setHost(qsh);
}
+ public void setPanelView(NotificationPanelView panelView) {
+ mPanelView = panelView;
+ }
+
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Since we control our own bottom, be whatever size we want.
// Otherwise the QSPanel ends up with 0 height when the window is only the
// size of the status bar.
super.onMeasure(widthMeasureSpec, MeasureSpec.UNSPECIFIED);
+
+ // QSCustomizer is always be the height of the screen, but do this after
+ // other measuring to avoid changing the height of the QSContainer.
+ getDisplay().getRealSize(mSizePoint);
+ mQSCustomizer.measure(widthMeasureSpec,
+ MeasureSpec.makeMeasureSpec(mSizePoint.y, MeasureSpec.EXACTLY));
}
@Override
@@ -88,6 +107,10 @@
updateBottom();
}
+ public boolean isCustomizing() {
+ return mQSCustomizer.isCustomizing();
+ }
+
/**
* 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.
@@ -104,6 +127,9 @@
* during closing the detail panel, this already returns the smaller height.
*/
public int getDesiredHeight() {
+ if (isCustomizing()) {
+ return getHeight();
+ }
if (mQSDetail.isClosingDetail()) {
return mQSPanel.getGridHeight() + mHeader.getCollapsedHeight() + getPaddingBottom();
} else {
@@ -111,9 +137,18 @@
}
}
+ public void notifyCustomizeChanged() {
+ // The customize state changed, so our height changed.
+ updateBottom();
+ // Let the panel know the position changed and it needs to update where notifications
+ // and whatnot are.
+ mPanelView.onQsHeightChanged();
+ }
+
private void updateBottom() {
int heightOverride = mHeightOverride != -1 ? mHeightOverride : getMeasuredHeight();
- int height = (int) (mQsExpansion * (heightOverride - mHeader.getCollapsedHeight()))
+ int height = mQSCustomizer.isCustomizing() ? mQSCustomizer.getHeight()
+ : (int) (mQsExpansion * (heightOverride - mHeader.getCollapsedHeight()))
+ mHeader.getCollapsedHeight();
setBottom(getTop() + height);
mQSDetail.setBottom(getTop() + height);
@@ -138,6 +173,10 @@
return mQSPanel;
}
+ public QSCustomizer getCustomizer() {
+ return mQSCustomizer;
+ }
+
public boolean isShowingDetail() {
return mQSPanel.isShowingCustomize() || mQSDetail.isShowingDetail();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 71c1913..899b0ef 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -155,12 +155,6 @@
return mHost.createTile(subPanel);
}
- protected void createCustomizePanel() {
- mCustomizePanel = (QSCustomizer) LayoutInflater.from(mContext)
- .inflate(R.layout.qs_customize_panel, null);
- mCustomizePanel.setHost(mHost);
- }
-
public void setBrightnessMirror(BrightnessMirrorController c) {
super.onFinishInflate();
ToggleSlider brightnessSlider = (ToggleSlider) findViewById(R.id.brightness_slider);
@@ -173,12 +167,15 @@
mCallback = callback;
}
- public void setHost(QSTileHost host) {
+ public void setHost(QSTileHost host, QSCustomizer customizer) {
mHost = host;
mHost.addCallback(this);
setTiles(mHost.getTiles());
mFooter.setHost(host);
- createCustomizePanel();
+ mCustomizePanel = customizer;
+ if (mCustomizePanel != null) {
+ mCustomizePanel.setHost(mHost);
+ }
}
public QSTileHost getHost() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index f8a57d0..d0e034b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -67,11 +67,6 @@
TunerService.get(mContext).removeTunable(mNumTiles);
}
- @Override
- protected void createCustomizePanel() {
- // No customizing from the header.
- }
-
public void setQSPanelAndHeader(QSPanel fullPanel, View header) {
mFullPanel = fullPanel;
mHeader = header;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index 5e02428..068efa6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -32,8 +32,10 @@
import android.widget.Toolbar;
import android.widget.Toolbar.OnMenuItemClickListener;
import com.android.systemui.R;
+import com.android.systemui.qs.QSContainer;
import com.android.systemui.qs.QSDetailClipper;
import com.android.systemui.qs.QSTile;
+import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
import com.android.systemui.statusbar.phone.QSTileHost;
@@ -59,6 +61,9 @@
private RecyclerView mRecyclerView;
private TileAdapter mTileAdapter;
private Toolbar mToolbar;
+ private boolean mCustomizing;
+ private NotificationsQuickSettingsContainer mNotifQsContainer;
+ private QSContainer mQsContainer;
public QSCustomizer(Context context, AttributeSet attrs) {
super(new ContextThemeWrapper(context, android.R.style.Theme_Material), attrs);
@@ -70,6 +75,14 @@
mPhoneStatusBar = host.getPhoneStatusBar();
}
+ public void setContainer(NotificationsQuickSettingsContainer notificationsQsContainer) {
+ mNotifQsContainer = notificationsQsContainer;
+ }
+
+ public void setQsContainer(QSContainer qsContainer) {
+ mQsContainer = qsContainer;
+ }
+
@Override
protected void onFinishInflate() {
super.onFinishInflate();
@@ -105,23 +118,31 @@
public void show(int x, int y) {
if (!isShown) {
isShown = true;
- mPhoneStatusBar.getStatusBarWindow().addView(this);
setTileSpecs();
- mClipper.animateCircularClip(x, y, true, null);
+ setVisibility(View.VISIBLE);
+ mClipper.animateCircularClip(x, y, true, mExpandAnimationListener);
new TileQueryHelper(mContext, mHost).setListener(mTileAdapter);
+ mNotifQsContainer.setCustomizerAnimating(true);
}
}
public void hide(int x, int y) {
if (isShown) {
isShown = false;
+ setCustomizing(false);
save();
mClipper.animateCircularClip(x, y, false, mCollapseAnimationListener);
+ mNotifQsContainer.setCustomizerAnimating(true);
}
}
+ private void setCustomizing(boolean customizing) {
+ mCustomizing = customizing;
+ mQsContainer.notifyCustomizeChanged();
+ }
+
public boolean isCustomizing() {
- return isShown;
+ return mCustomizing;
}
@Override
@@ -155,19 +176,34 @@
mTileAdapter.saveSpecs(mHost);
}
+ private final AnimatorListener mExpandAnimationListener = new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ setCustomizing(true);
+ mNotifQsContainer.setCustomizerAnimating(false);
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mNotifQsContainer.setCustomizerAnimating(false);
+ }
+ };
+
private final AnimatorListener mCollapseAnimationListener = new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (!isShown) {
- mPhoneStatusBar.getStatusBarWindow().removeView(QSCustomizer.this);
+ setVisibility(View.GONE);
}
+ mNotifQsContainer.setCustomizerAnimating(false);
}
@Override
public void onAnimationCancel(Animator animation) {
if (!isShown) {
- mPhoneStatusBar.getStatusBarWindow().removeView(QSCustomizer.this);
+ setVisibility(View.GONE);
}
+ mNotifQsContainer.setCustomizerAnimating(false);
}
};
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 88b8afa..9c6f2c5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -65,7 +65,7 @@
import java.util.List;
public class NotificationPanelView extends PanelView implements
- ExpandableView.OnHeightChangedListener, ObservableScrollView.Listener,
+ ExpandableView.OnHeightChangedListener,
View.OnClickListener, NotificationStackScrollLayout.OnOverscrollTopChangedListener,
KeyguardAffordanceHelper.Callback, NotificationStackScrollLayout.OnEmptySpaceClickListener,
HeadsUpManager.OnHeadsUpChangedListener {
@@ -222,6 +222,7 @@
@Override
public void onInflated(View v) {
mQsContainer = (QSContainer) v.findViewById(R.id.quick_settings_container);
+ mQsContainer.setPanelView(NotificationPanelView.this);
mQsContainer.getHeader().setOnClickListener(NotificationPanelView.this);
}
});
@@ -247,7 +248,7 @@
final int height = bottom - top;
final int oldHeight = oldBottom - oldTop;
if (height != oldHeight) {
- onScrollChanged();
+ onQsHeightChanged();
}
}
});
@@ -547,7 +548,7 @@
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
- if (mBlockTouches) {
+ if (mBlockTouches || mQsContainer.isCustomizing()) {
return false;
}
initDownStates(event);
@@ -707,7 +708,7 @@
@Override
public boolean onTouchEvent(MotionEvent event) {
- if (mBlockTouches) {
+ if (mBlockTouches || mQsContainer.isCustomizing()) {
return false;
}
initDownStates(event);
@@ -906,18 +907,6 @@
}
@Override
- public void onOverscrolled(float lastTouchX, float lastTouchY, int amount) {
- if (mIntercepting && shouldQuickSettingsIntercept(lastTouchX, lastTouchY,
- -1 /* yDiff: Not relevant here */)) {
- mQsTracking = true;
- onQsExpansionStarted(amount);
- mInitialHeightOnTouch = mQsExpansionHeight;
- mInitialTouchY = mLastTouchY;
- mInitialTouchX = mLastTouchX;
- }
- }
-
- @Override
public void onOverscrollTopChanged(float amount, boolean isRubberbanded) {
cancelQsAnimation();
if (!mQsExpansionEnabled) {
@@ -1719,9 +1708,10 @@
public void onReset(ExpandableView view) {
}
- @Override
- public void onScrollChanged() {
+ public void onQsHeightChanged() {
+ mQsMaxExpansionHeight = mQsContainer.getDesiredHeight();
if (mQsExpanded) {
+ mQsExpansionHeight = mQsMaxExpansionHeight;
requestScrollerTopPaddingUpdate(false /* animate */);
requestPanelHeightUpdate();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
index 6d90e5c..f0df706 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
@@ -24,21 +24,24 @@
import android.view.ViewStub;
import android.view.WindowInsets;
import android.widget.FrameLayout;
-
+import com.android.systemui.DensityContainer;
import com.android.systemui.R;
+import com.android.systemui.qs.QSContainer;
+import com.android.systemui.qs.customize.QSCustomizer;
/**
* The container with notification stack scroller and quick settings inside.
*/
public class NotificationsQuickSettingsContainer extends FrameLayout
- implements ViewStub.OnInflateListener {
+ implements ViewStub.OnInflateListener, DensityContainer.InflateListener {
- private View mQsContainer;
+ private DensityContainer mQsContainer;
private View mUserSwitcher;
private View mStackScroller;
private View mKeyguardStatusBar;
private boolean mInflated;
private boolean mQsExpanded;
+ private boolean mCustomizerAnimating;
public NotificationsQuickSettingsContainer(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -47,7 +50,8 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mQsContainer = findViewById(R.id.qs_density_container);
+ mQsContainer = (DensityContainer) findViewById(R.id.qs_density_container);
+ mQsContainer.addInflateListener(this);
mStackScroller = findViewById(R.id.notification_stack_scroller);
mKeyguardStatusBar = findViewById(R.id.keyguard_header);
ViewStub userSwitcher = (ViewStub) findViewById(R.id.keyguard_user_switcher);
@@ -80,8 +84,9 @@
boolean userSwitcherVisible = mInflated && mUserSwitcher.getVisibility() == View.VISIBLE;
boolean statusBarVisible = mKeyguardStatusBar.getVisibility() == View.VISIBLE;
- View stackQsTop = mQsExpanded ? mStackScroller : mQsContainer;
- View stackQsBottom = !mQsExpanded ? mStackScroller : mQsContainer;
+ final boolean qsBottom = mQsExpanded && !mCustomizerAnimating;
+ View stackQsTop = qsBottom ? mStackScroller : mQsContainer;
+ View stackQsBottom = !qsBottom ? mStackScroller : mQsContainer;
// Invert the order of the scroll view and user switcher such that the notifications receive
// touches first but the panel gets drawn above.
if (child == mQsContainer) {
@@ -117,10 +122,23 @@
}
}
+ @Override
+ public void onInflated(View v) {
+ QSCustomizer customizer = ((QSContainer) v).getCustomizer();
+ customizer.setContainer(this);
+ }
+
public void setQsExpanded(boolean expanded) {
if (mQsExpanded != expanded) {
mQsExpanded = expanded;
invalidate();
}
}
+
+ public void setCustomizerAnimating(boolean isAnimating) {
+ if (mCustomizerAnimating != isAnimating) {
+ mCustomizerAnimating = isAnimating;
+ invalidate();
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
index 326ca2b..b29c807 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
@@ -296,7 +296,7 @@
mHost = host;
host.setHeaderView(this);
mHeaderQsPanel.setQSPanelAndHeader(mQsPanel, this);
- mHeaderQsPanel.setHost(host);
+ mHeaderQsPanel.setHost(host, null /* No customization in header */);
setUserInfoController(host.getUserInfoController());
setBatteryController(host.getBatteryController());
setNextAlarmController(host.getNextAlarmController());