Move QS to a fragment
There is now a bit too much of the view/layout logic touching the
fragment, but sort out that later and get something over to fragments
for now.
Bug: 32609190
Test: Manual
Change-Id: Icf677f4a70e6b92892a0fc27a0e673940ebc7a73
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index e1cd143..dc42adc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -20,7 +20,7 @@
import android.view.View.OnLayoutChangeListener;
import android.widget.TextView;
-import com.android.systemui.plugins.qs.QSContainer;
+import com.android.systemui.plugins.qs.QS;
import com.android.systemui.qs.PagedTileLayout.PageListener;
import com.android.systemui.qs.QSPanel.QSTileLayout;
import com.android.systemui.qs.QSTile.Host.Callback;
@@ -47,7 +47,7 @@
private final ArrayList<View> mTopFiveQs = new ArrayList<>();
private final QuickQSPanel mQuickQsPanel;
private final QSPanel mQsPanel;
- private final QSContainer mQsContainer;
+ private final QS mQs;
private PagedTileLayout mPagedLayout;
@@ -67,12 +67,15 @@
private float mLastPosition;
private QSTileHost mHost;
- public QSAnimator(QSContainer container, QuickQSPanel quickPanel, QSPanel panel) {
- mQsContainer = container;
+ public QSAnimator(QS qs, QuickQSPanel quickPanel, QSPanel panel) {
+ mQs = qs;
mQuickQsPanel = quickPanel;
mQsPanel = panel;
mQsPanel.addOnAttachStateChangeListener(this);
- container.addOnLayoutChangeListener(this);
+ qs.getView().addOnLayoutChangeListener(this);
+ if (mQsPanel.isAttachedToWindow()) {
+ onViewAttachedToWindow(null);
+ }
QSTileLayout tileLayout = mQsPanel.getTileLayout();
if (tileLayout instanceof PagedTileLayout) {
mPagedLayout = ((PagedTileLayout) tileLayout);
@@ -102,7 +105,7 @@
@Override
public void onViewAttachedToWindow(View v) {
- TunerService.get(mQsContainer.getContext()).addTunable(this, ALLOW_FANCY_ANIMATION,
+ TunerService.get(mQs.getContext()).addTunable(this, ALLOW_FANCY_ANIMATION,
MOVE_FULL_ROWS, QuickQSPanel.NUM_QUICK_TILES);
}
@@ -111,7 +114,7 @@
if (mHost != null) {
mHost.removeCallback(this);
}
- TunerService.get(mQsContainer.getContext()).removeTunable(this);
+ TunerService.get(mQs.getContext()).removeTunable(this);
}
@Override
@@ -124,7 +127,7 @@
} else if (MOVE_FULL_ROWS.equals(key)) {
mFullRows = newValue == null || Integer.parseInt(newValue) != 0;
} else if (QuickQSPanel.NUM_QUICK_TILES.equals(key)) {
- mNumQuickTiles = mQuickQsPanel.getNumQuickTiles(mQsContainer.getContext());
+ mNumQuickTiles = mQuickQsPanel.getNumQuickTiles(mQs.getContext());
clearAnimationState();
}
updateAnimators();
@@ -166,13 +169,14 @@
}
final TextView label = ((QSTileView) tileView).getLabel();
final View tileIcon = tileView.getIcon().getIconView();
+ View view = mQs.getView();
if (count < mNumQuickTiles && mAllowFancy) {
// Quick tiles.
QSTileBaseView quickTileView = mQuickQsPanel.getTileView(tile);
lastX = loc1[0];
- getRelativePosition(loc1, quickTileView.getIcon().getIconView(), mQsContainer);
- getRelativePosition(loc2, tileIcon, mQsContainer);
+ getRelativePosition(loc1, quickTileView.getIcon().getIconView(), view);
+ getRelativePosition(loc2, tileIcon, view);
final int xDiff = loc2[0] - loc1[0];
final int yDiff = loc2[1] - loc1[1];
lastXDiff = loc1[0] - lastX;
@@ -198,7 +202,7 @@
// This makes the extra icons seems as if they are coming from positions in the
// quick panel.
loc1[0] += lastXDiff;
- getRelativePosition(loc2, tileIcon, mQsContainer);
+ getRelativePosition(loc2, tileIcon, view);
final int xDiff = loc2[0] - loc1[0];
final int yDiff = loc2[1] - loc1[1];
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index f345172..f4da5ec 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -16,53 +16,34 @@
package com.android.systemui.qs;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.AttributeSet;
-import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
+import android.widget.FrameLayout;
-import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.plugins.qs.QSContainer;
+import com.android.systemui.plugins.qs.QS.HeightListener;
import com.android.systemui.qs.customize.QSCustomizer;
import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer;
import com.android.systemui.statusbar.phone.QSTileHost;
import com.android.systemui.statusbar.phone.QuickStatusBarHeader;
-import com.android.systemui.statusbar.stack.StackStateAnimator;
/**
* Wrapper view with background which contains {@link QSPanel} and {@link BaseStatusBarHeader}
- *
- * Also manages animations for the QS Header and Panel.
*/
-public class QSContainerImpl extends QSContainer {
- private static final String TAG = "QSContainer";
- private static final boolean DEBUG = false;
+public class QSContainerImpl extends FrameLayout {
private final Point mSizePoint = new Point();
- private final Rect mQsBounds = new Rect();
private int mHeightOverride = -1;
- protected QSPanel mQSPanel;
- private QSDetail mQSDetail;
- protected QuickStatusBarHeader mHeader;
+ protected View mQSPanel;
+ private View mQSDetail;
+ protected View mHeader;
protected float mQsExpansion;
- private boolean mQsExpanded;
- private boolean mHeaderAnimating;
- private boolean mKeyguardShowing;
- private boolean mStackScrollerOverscrolling;
-
- private long mDelay;
- private QSAnimator mQSAnimator;
private QSCustomizer mQSCustomizer;
- private HeightListener mPanelView;
- private boolean mListening;
public QSContainerImpl(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -71,31 +52,10 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mQSPanel = (QSPanel) findViewById(R.id.quick_settings_panel);
- mQSDetail = (QSDetail) findViewById(R.id.qs_detail);
- mHeader = (QuickStatusBarHeader) findViewById(R.id.header);
- mQSDetail.setQsPanel(mQSPanel, mHeader);
- mQSAnimator = new QSAnimator(this, (QuickQSPanel) mHeader.findViewById(R.id.quick_qs_panel),
- mQSPanel);
+ mQSPanel = findViewById(R.id.quick_settings_panel);
+ mQSDetail = findViewById(R.id.qs_detail);
+ mHeader = findViewById(R.id.header);
mQSCustomizer = (QSCustomizer) findViewById(R.id.qs_customize);
- mQSCustomizer.setQsContainer(this);
- }
-
- @Override
- public void onRtlPropertiesChanged(int layoutDirection) {
- super.onRtlPropertiesChanged(layoutDirection);
- mQSAnimator.onRtlChanged();
- }
-
- public void setHost(QSTileHost qsh) {
- mQSPanel.setHost(qsh, mQSCustomizer);
- mHeader.setQSPanel(mQSPanel);
- mQSDetail.setHost(qsh);
- mQSAnimator.setHost(qsh);
- }
-
- public void setPanelView(HeightListener panelView) {
- mPanelView = panelView;
}
@Override
@@ -111,8 +71,8 @@
super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
- // QSCustomizer is always be the height of the screen, but do this after
- // other measuring to avoid changing the height of the QSContainer.
+ // QSCustomizer will always be the height of the screen, but do this after
+ // other measuring to avoid changing the height of the QS.
getDisplay().getRealSize(mSizePoint);
mQSCustomizer.measure(widthMeasureSpec,
MeasureSpec.makeMeasureSpec(mSizePoint.y, MeasureSpec.EXACTLY));
@@ -124,10 +84,6 @@
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.
@@ -139,41 +95,7 @@
updateBottom();
}
- @Override
- public void setContainer(ViewGroup container) {
- if (container instanceof NotificationsQuickSettingsContainer) {
- mQSCustomizer.setContainer((NotificationsQuickSettingsContainer) container);
- }
- }
-
- /**
- * 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 (isCustomizing()) {
- return getHeight();
- }
- if (mQSDetail.isClosingDetail()) {
- int panelHeight = ((LayoutParams) mQSPanel.getLayoutParams()).topMargin
- + mQSPanel.getMeasuredHeight();
- return panelHeight + getPaddingBottom();
- } else {
- return getMeasuredHeight();
- }
- }
-
- public void notifyCustomizeChanged() {
- // The customize state changed, so our height changed.
- updateBottom();
- mQSPanel.setVisibility(!mQSCustomizer.isCustomizing() ? View.VISIBLE : View.INVISIBLE);
- mHeader.setVisibility(!mQSCustomizer.isCustomizing() ? View.VISIBLE : View.INVISIBLE);
- // Let the panel know the position changed and it needs to update where notifications
- // and whatnot are.
- mPanelView.onQsHeightChanged();
- }
-
- private void updateBottom() {
+ void updateBottom() {
int height = calculateContainerHeight();
setBottom(getTop() + height);
mQSDetail.setBottom(getTop() + height);
@@ -182,162 +104,12 @@
protected int calculateContainerHeight() {
int heightOverride = mHeightOverride != -1 ? mHeightOverride : getMeasuredHeight();
return mQSCustomizer.isCustomizing() ? mQSCustomizer.getHeight()
- : (int) (mQsExpansion * (heightOverride - mHeader.getCollapsedHeight()))
- + mHeader.getCollapsedHeight();
+ : (int) (mQsExpansion * (heightOverride - mHeader.getHeight()))
+ + mHeader.getHeight();
}
- private void updateQsState() {
- boolean expandVisually = mQsExpanded || mStackScrollerOverscrolling || mHeaderAnimating;
- mQSPanel.setExpanded(mQsExpanded);
- mQSDetail.setExpanded(mQsExpanded);
- mHeader.setVisibility((mQsExpanded || !mKeyguardShowing || mHeaderAnimating)
- ? View.VISIBLE
- : View.INVISIBLE);
- mHeader.setExpanded((mKeyguardShowing && !mHeaderAnimating)
- || (mQsExpanded && !mStackScrollerOverscrolling));
- mQSPanel.setVisibility(expandVisually ? View.VISIBLE : View.INVISIBLE);
- }
-
- public BaseStatusBarHeader getHeader() {
- return mHeader;
- }
-
- public QSPanel getQsPanel() {
- return mQSPanel;
- }
-
- public QSCustomizer getCustomizer() {
- return mQSCustomizer;
- }
-
- public boolean isShowingDetail() {
- return mQSPanel.isShowingCustomize() || mQSDetail.isShowingDetail();
- }
-
- public void setHeaderClickable(boolean clickable) {
- if (DEBUG) Log.d(TAG, "setHeaderClickable " + clickable);
- mHeader.setClickable(clickable);
- }
-
- public void setExpanded(boolean expanded) {
- if (DEBUG) Log.d(TAG, "setExpanded " + expanded);
- mQsExpanded = expanded;
- mQSPanel.setListening(mListening && mQsExpanded);
- updateQsState();
- }
-
- public void setKeyguardShowing(boolean keyguardShowing) {
- if (DEBUG) Log.d(TAG, "setKeyguardShowing " + keyguardShowing);
- mKeyguardShowing = keyguardShowing;
- mQSAnimator.setOnKeyguard(keyguardShowing);
- updateQsState();
- }
-
- public void setOverscrolling(boolean stackScrollerOverscrolling) {
- if (DEBUG) Log.d(TAG, "setOverscrolling " + stackScrollerOverscrolling);
- mStackScrollerOverscrolling = stackScrollerOverscrolling;
- updateQsState();
- }
-
- public void setListening(boolean listening) {
- if (DEBUG) Log.d(TAG, "setListening " + listening);
- mListening = listening;
- mHeader.setListening(listening);
- mQSPanel.setListening(mListening && mQsExpanded);
- }
-
- public void setHeaderListening(boolean listening) {
- mHeader.setListening(listening);
- }
-
- public void setQsExpansion(float expansion, float headerTranslation) {
- if (DEBUG) Log.d(TAG, "setQSExpansion " + expansion + " " + headerTranslation);
+ public void setExpansion(float expansion) {
mQsExpansion = expansion;
- final float translationScaleY = expansion - 1;
- if (!mHeaderAnimating) {
- setTranslationY(mKeyguardShowing ? (translationScaleY * mHeader.getHeight())
- : headerTranslation);
- }
- mHeader.setExpansion(mKeyguardShowing ? 1 : expansion);
- mQSPanel.setTranslationY(translationScaleY * mQSPanel.getHeight());
- mQSDetail.setFullyExpanded(expansion == 1);
- mQSAnimator.setPosition(expansion);
updateBottom();
-
- // Set bounds on the QS panel so it doesn't run over the header.
- mQsBounds.top = (int) (mQSPanel.getHeight() * (1 - expansion));
- mQsBounds.right = mQSPanel.getWidth();
- mQsBounds.bottom = mQSPanel.getHeight();
- mQSPanel.setClipBounds(mQsBounds);
- }
-
- public void animateHeaderSlidingIn(long delay) {
- if (DEBUG) Log.d(TAG, "animateHeaderSlidingIn");
- // If the QS is already expanded we don't need to slide in the header as it's already
- // visible.
- if (!mQsExpanded) {
- mHeaderAnimating = true;
- mDelay = delay;
- getViewTreeObserver().addOnPreDrawListener(mStartHeaderSlidingIn);
- }
- }
-
- public void animateHeaderSlidingOut() {
- if (DEBUG) Log.d(TAG, "animateHeaderSlidingOut");
- mHeaderAnimating = true;
- animate().y(-mHeader.getHeight())
- .setStartDelay(0)
- .setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD)
- .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- animate().setListener(null);
- mHeaderAnimating = false;
- updateQsState();
- }
- })
- .start();
- }
-
- @Override
- public void closeDetail() {
- mQSPanel.closeDetail();
- }
-
- private final ViewTreeObserver.OnPreDrawListener mStartHeaderSlidingIn
- = new ViewTreeObserver.OnPreDrawListener() {
- @Override
- public boolean onPreDraw() {
- getViewTreeObserver().removeOnPreDrawListener(this);
- animate()
- .translationY(0f)
- .setStartDelay(mDelay)
- .setDuration(StackStateAnimator.ANIMATION_DURATION_GO_TO_FULL_SHADE)
- .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
- .setListener(mAnimateHeaderSlidingInListener)
- .start();
- setY(-mHeader.getHeight());
- return true;
- }
- };
-
- private final Animator.AnimatorListener mAnimateHeaderSlidingInListener
- = new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mHeaderAnimating = false;
- updateQsState();
- }
- };
-
- public int getQsMinExpansionHeight() {
- return mHeader.getHeight();
- }
-
- @Override
- public void hideImmediately() {
- animate().cancel();
- setY(-mHeader.getHeight());
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
index 2b9320b..5027144 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
@@ -35,9 +35,9 @@
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
-import com.android.systemui.plugins.qs.QSContainer.BaseStatusBarHeader;
-import com.android.systemui.plugins.qs.QSContainer.Callback;
-import com.android.systemui.plugins.qs.QSContainer.DetailAdapter;
+import com.android.systemui.plugins.qs.QS.BaseStatusBarHeader;
+import com.android.systemui.plugins.qs.QS.Callback;
+import com.android.systemui.plugins.qs.QS.DetailAdapter;
import com.android.systemui.statusbar.phone.QSTileHost;
public class QSDetail extends LinearLayout {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
new file mode 100644
index 0000000..c8f1670
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2016 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.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.annotation.Nullable;
+import android.app.Fragment;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.widget.FrameLayout.LayoutParams;
+
+import com.android.systemui.Interpolators;
+import com.android.systemui.R;
+import com.android.systemui.plugins.qs.QS;
+import com.android.systemui.qs.customize.QSCustomizer;
+import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer;
+import com.android.systemui.statusbar.phone.QSTileHost;
+import com.android.systemui.statusbar.phone.QuickStatusBarHeader;
+import com.android.systemui.statusbar.stack.StackStateAnimator;
+
+public class QSFragment extends Fragment implements QS {
+ private static final String TAG = "QS";
+ private static final boolean DEBUG = false;
+
+ private final Rect mQsBounds = new Rect();
+ private boolean mQsExpanded;
+ private boolean mHeaderAnimating;
+ private boolean mKeyguardShowing;
+ private boolean mStackScrollerOverscrolling;
+
+ private long mDelay;
+
+ private QSAnimator mQSAnimator;
+ private HeightListener mPanelView;
+ protected QuickStatusBarHeader mHeader;
+ private QSCustomizer mQSCustomizer;
+ protected QSPanel mQSPanel;
+ private QSDetail mQSDetail;
+ private boolean mListening;
+ private QSContainerImpl mContainer;
+ private int mLayoutDirection;
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.qs_panel, container, false);
+ }
+
+ @Override
+ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ mQSPanel = (QSPanel) view.findViewById(R.id.quick_settings_panel);
+ mQSDetail = (QSDetail) view.findViewById(R.id.qs_detail);
+ mHeader = (QuickStatusBarHeader) view.findViewById(R.id.header);
+ mContainer = (QSContainerImpl) view;
+
+ mQSDetail.setQsPanel(mQSPanel, mHeader);
+ mQSAnimator = new QSAnimator(this, (QuickQSPanel) mHeader.findViewById(R.id.quick_qs_panel),
+ mQSPanel);
+ mQSCustomizer = (QSCustomizer) view.findViewById(R.id.qs_customize);
+ mQSCustomizer.setQs(this);
+ }
+
+ public void setPanelView(HeightListener panelView) {
+ mPanelView = panelView;
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ if (newConfig.getLayoutDirection() != mLayoutDirection) {
+ mLayoutDirection = newConfig.getLayoutDirection();
+ mQSAnimator.onRtlChanged();
+ }
+ }
+
+ @Override
+ public void setContainer(ViewGroup container) {
+ if (container instanceof NotificationsQuickSettingsContainer) {
+ mQSCustomizer.setContainer((NotificationsQuickSettingsContainer) container);
+ }
+ }
+
+ public boolean isCustomizing() {
+ return mQSCustomizer.isCustomizing();
+ }
+
+ public void setHost(QSTileHost qsh) {
+ mQSPanel.setHost(qsh, mQSCustomizer);
+ mHeader.setQSPanel(mQSPanel);
+ mQSDetail.setHost(qsh);
+ mQSAnimator.setHost(qsh);
+ }
+
+ private void updateQsState() {
+ final boolean expandVisually = mQsExpanded || mStackScrollerOverscrolling
+ || mHeaderAnimating;
+ mQSPanel.setExpanded(mQsExpanded);
+ mQSDetail.setExpanded(mQsExpanded);
+ mHeader.setVisibility((mQsExpanded || !mKeyguardShowing || mHeaderAnimating)
+ ? View.VISIBLE
+ : View.INVISIBLE);
+ mHeader.setExpanded((mKeyguardShowing && !mHeaderAnimating)
+ || (mQsExpanded && !mStackScrollerOverscrolling));
+ mQSPanel.setVisibility(expandVisually ? View.VISIBLE : View.INVISIBLE);
+ }
+
+ public BaseStatusBarHeader getHeader() {
+ return mHeader;
+ }
+
+ public QSPanel getQsPanel() {
+ return mQSPanel;
+ }
+
+ public QSCustomizer getCustomizer() {
+ return mQSCustomizer;
+ }
+
+ public boolean isShowingDetail() {
+ return mQSPanel.isShowingCustomize() || mQSDetail.isShowingDetail();
+ }
+
+ public void setHeaderClickable(boolean clickable) {
+ if (DEBUG) Log.d(TAG, "setHeaderClickable " + clickable);
+ mHeader.setClickable(clickable);
+ }
+
+ public void setExpanded(boolean expanded) {
+ if (DEBUG) Log.d(TAG, "setExpanded " + expanded);
+ mQsExpanded = expanded;
+ mQSPanel.setListening(mListening && mQsExpanded);
+ updateQsState();
+ }
+
+ public void setKeyguardShowing(boolean keyguardShowing) {
+ if (DEBUG) Log.d(TAG, "setKeyguardShowing " + keyguardShowing);
+ mKeyguardShowing = keyguardShowing;
+ mQSAnimator.setOnKeyguard(keyguardShowing);
+ updateQsState();
+ }
+
+ public void setOverscrolling(boolean stackScrollerOverscrolling) {
+ if (DEBUG) Log.d(TAG, "setOverscrolling " + stackScrollerOverscrolling);
+ mStackScrollerOverscrolling = stackScrollerOverscrolling;
+ updateQsState();
+ }
+
+ public void setListening(boolean listening) {
+ if (DEBUG) Log.d(TAG, "setListening " + listening);
+ mListening = listening;
+ mHeader.setListening(listening);
+ mQSPanel.setListening(mListening && mQsExpanded);
+ }
+
+ public void setHeaderListening(boolean listening) {
+ mHeader.setListening(listening);
+ }
+
+ public void setQsExpansion(float expansion, float headerTranslation) {
+ if (DEBUG) Log.d(TAG, "setQSExpansion " + expansion + " " + headerTranslation);
+ mContainer.setExpansion(expansion);
+ final float translationScaleY = expansion - 1;
+ if (!mHeaderAnimating) {
+ getView().setTranslationY(mKeyguardShowing ? (translationScaleY * mHeader.getHeight())
+ : headerTranslation);
+ }
+ mHeader.setExpansion(mKeyguardShowing ? 1 : expansion);
+ mQSPanel.setTranslationY(translationScaleY * mQSPanel.getHeight());
+ mQSDetail.setFullyExpanded(expansion == 1);
+ mQSAnimator.setPosition(expansion);
+
+ // Set bounds on the QS panel so it doesn't run over the header.
+ mQsBounds.top = (int) (mQSPanel.getHeight() * (1 - expansion));
+ mQsBounds.right = mQSPanel.getWidth();
+ mQsBounds.bottom = mQSPanel.getHeight();
+ mQSPanel.setClipBounds(mQsBounds);
+ }
+
+ public void animateHeaderSlidingIn(long delay) {
+ if (DEBUG) Log.d(TAG, "animateHeaderSlidingIn");
+ // If the QS is already expanded we don't need to slide in the header as it's already
+ // visible.
+ if (!mQsExpanded) {
+ mHeaderAnimating = true;
+ mDelay = delay;
+ getView().getViewTreeObserver().addOnPreDrawListener(mStartHeaderSlidingIn);
+ }
+ }
+
+ public void animateHeaderSlidingOut() {
+ if (DEBUG) Log.d(TAG, "animateHeaderSlidingOut");
+ mHeaderAnimating = true;
+ getView().animate().y(-mHeader.getHeight())
+ .setStartDelay(0)
+ .setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD)
+ .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ getView().animate().setListener(null);
+ mHeaderAnimating = false;
+ updateQsState();
+ }
+ })
+ .start();
+ }
+
+ @Override
+ public void closeDetail() {
+ mQSPanel.closeDetail();
+ }
+
+ public void notifyCustomizeChanged() {
+ // The customize state changed, so our height changed.
+ mContainer.updateBottom();
+ mQSPanel.setVisibility(!mQSCustomizer.isCustomizing() ? View.VISIBLE : View.INVISIBLE);
+ mHeader.setVisibility(!mQSCustomizer.isCustomizing() ? View.VISIBLE : View.INVISIBLE);
+ // Let the panel know the position changed and it needs to update where notifications
+ // and whatnot are.
+ mPanelView.onQsHeightChanged();
+ }
+
+ /**
+ * 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 (mQSCustomizer.isCustomizing()) {
+ return getView().getHeight();
+ }
+ if (mQSDetail.isClosingDetail()) {
+ int panelHeight = ((LayoutParams) mQSPanel.getLayoutParams()).topMargin
+ + mQSPanel.getMeasuredHeight();
+ return panelHeight + getView().getPaddingBottom();
+ } else {
+ return getView().getMeasuredHeight();
+ }
+ }
+
+ @Override
+ public void setHeightOverride(int desiredHeight) {
+ mContainer.setHeightOverride(desiredHeight);
+ }
+
+ public int getQsMinExpansionHeight() {
+ return mHeader.getHeight();
+ }
+
+ @Override
+ public void hideImmediately() {
+ getView().animate().cancel();
+ getView().setY(-mHeader.getHeight());
+ }
+
+ private final ViewTreeObserver.OnPreDrawListener mStartHeaderSlidingIn
+ = new ViewTreeObserver.OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ getView().getViewTreeObserver().removeOnPreDrawListener(this);
+ getView().animate()
+ .translationY(0f)
+ .setStartDelay(mDelay)
+ .setDuration(StackStateAnimator.ANIMATION_DURATION_GO_TO_FULL_SHADE)
+ .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
+ .setListener(mAnimateHeaderSlidingInListener)
+ .start();
+ getView().setY(-mHeader.getHeight());
+ return true;
+ }
+ };
+
+ private final Animator.AnimatorListener mAnimateHeaderSlidingInListener
+ = new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mHeaderAnimating = false;
+ updateQsState();
+ }
+ };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 49307d8..e55ff70 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -30,8 +30,8 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.R;
-import com.android.systemui.plugins.qs.QSContainer;
-import com.android.systemui.plugins.qs.QSContainer.DetailAdapter;
+import com.android.systemui.plugins.qs.QS;
+import com.android.systemui.plugins.qs.QS.DetailAdapter;
import com.android.systemui.qs.QSTile.Host.Callback;
import com.android.systemui.qs.customize.QSCustomizer;
import com.android.systemui.qs.external.CustomTile;
@@ -60,7 +60,7 @@
protected boolean mExpanded;
protected boolean mListening;
- private QSContainer.Callback mCallback;
+ private QS.Callback mCallback;
private BrightnessController mBrightnessController;
protected QSTileHost mHost;
@@ -171,7 +171,7 @@
return mBrightnessView;
}
- public void setCallback(QSContainer.Callback callback) {
+ public void setCallback(QS.Callback callback) {
mCallback = callback;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index 6856575..4341d17 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -31,7 +31,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settingslib.RestrictedLockUtils;
-import com.android.systemui.plugins.qs.QSContainer.DetailAdapter;
+import com.android.systemui.plugins.qs.QS.DetailAdapter;
import com.android.systemui.qs.QSTile.State;
import com.android.systemui.qs.external.TileServices;
import com.android.systemui.statusbar.phone.ManagedProfileController;
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 f663c75..9bbead4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -37,7 +37,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
import com.android.systemui.R;
-import com.android.systemui.plugins.qs.QSContainer;
+import com.android.systemui.plugins.qs.QS;
import com.android.systemui.qs.QSDetailClipper;
import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer;
@@ -69,7 +69,7 @@
private Toolbar mToolbar;
private boolean mCustomizing;
private NotificationsQuickSettingsContainer mNotifQsContainer;
- private QSContainer mQsContainer;
+ private QS mQs;
public QSCustomizer(Context context, AttributeSet attrs) {
super(new ContextThemeWrapper(context, R.style.edit_theme), attrs);
@@ -127,8 +127,8 @@
mNotifQsContainer = notificationsQsContainer;
}
- public void setQsContainer(QSContainer qsContainer) {
- mQsContainer = qsContainer;
+ public void setQs(QS qs) {
+ mQs = qs;
}
public void show(int x, int y) {
@@ -169,7 +169,7 @@
private void setCustomizing(boolean customizing) {
mCustomizing = customizing;
- mQsContainer.notifyCustomizeChanged();
+ mQs.notifyCustomizeChanged();
}
public boolean isCustomizing() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
index e5a555a..70f9b04 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
@@ -20,8 +20,6 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.drawable.Drawable;
-import android.os.Handler;
-import android.os.Looper;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.style.RelativeSizeSpan;
@@ -40,7 +38,7 @@
import com.android.settingslib.graph.UsageView;
import com.android.systemui.BatteryMeterDrawable;
import com.android.systemui.R;
-import com.android.systemui.plugins.qs.QSContainer.DetailAdapter;
+import com.android.systemui.plugins.qs.QS.DetailAdapter;
import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.policy.BatteryController;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index 53010af..4266549 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -32,7 +32,7 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.systemui.R;
-import com.android.systemui.plugins.qs.QSContainer.DetailAdapter;
+import com.android.systemui.plugins.qs.QS.DetailAdapter;
import com.android.systemui.qs.QSDetailItems;
import com.android.systemui.qs.QSDetailItems.Item;
import com.android.systemui.qs.QSTile;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index 4abd84a..8afa91e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -28,7 +28,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.R;
-import com.android.systemui.plugins.qs.QSContainer.DetailAdapter;
+import com.android.systemui.plugins.qs.QS.DetailAdapter;
import com.android.systemui.qs.QSDetailItems;
import com.android.systemui.qs.QSDetailItems.Item;
import com.android.systemui.qs.QSTile;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 2183565..f23e940 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -29,7 +29,7 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settingslib.net.DataUsageController;
import com.android.systemui.R;
-import com.android.systemui.plugins.qs.QSContainer.DetailAdapter;
+import com.android.systemui.plugins.qs.QS.DetailAdapter;
import com.android.systemui.qs.QSIconView;
import com.android.systemui.qs.QSTile;
import com.android.systemui.qs.SignalTileView;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index 544ee91..198375d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -37,7 +37,7 @@
import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.SysUIToast;
-import com.android.systemui.plugins.qs.QSContainer.DetailAdapter;
+import com.android.systemui.plugins.qs.QS.DetailAdapter;
import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.volume.ZenModePanel;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
index e79e519..d5e2bdd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
@@ -22,7 +22,7 @@
import android.util.Pair;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.plugins.qs.QSContainer.DetailAdapter;
+import com.android.systemui.plugins.qs.QS.DetailAdapter;
import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index 9ce748f6..d5e8000 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -31,7 +31,7 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settingslib.wifi.AccessPoint;
import com.android.systemui.R;
-import com.android.systemui.plugins.qs.QSContainer.DetailAdapter;
+import com.android.systemui.plugins.qs.QS.DetailAdapter;
import com.android.systemui.qs.QSDetailItems;
import com.android.systemui.qs.QSDetailItems.Item;
import com.android.systemui.qs.QSIconView;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java
index baff680..1c8c317 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java
@@ -30,7 +30,7 @@
import android.widget.LinearLayout;
import com.android.systemui.R;
-import com.android.systemui.plugins.qs.QSContainer.ActivityStarter;
+import com.android.systemui.plugins.qs.QS.ActivityStarter;
import java.net.URISyntaxException;
import java.util.ArrayList;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index dfb06d7..dbae6b8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -66,7 +66,7 @@
import com.android.systemui.plugins.IntentButtonProvider.IntentButton.IconState;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.plugins.PluginManager;
-import com.android.systemui.plugins.qs.QSContainer.ActivityStarter;
+import com.android.systemui.plugins.qs.QS.ActivityStarter;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.KeyguardAffordanceView;
import com.android.systemui.statusbar.KeyguardIndicationController;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
index af9454c..4d4f9d2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
@@ -30,7 +30,7 @@
import android.widget.FrameLayout;
import com.android.systemui.R;
-import com.android.systemui.plugins.qs.QSContainer.DetailAdapter;
+import com.android.systemui.plugins.qs.QS.DetailAdapter;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
import com.android.systemui.statusbar.policy.UserSwitcherController;
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 cda0bfe..749b34e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -21,6 +21,7 @@
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.ActivityManager;
+import android.app.Fragment;
import android.app.StatusBarManager;
import android.content.Context;
import android.content.pm.ResolveInfo;
@@ -34,6 +35,7 @@
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
+import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.WindowInsets;
import android.view.accessibility.AccessibilityEvent;
@@ -42,15 +44,15 @@
import com.android.internal.logging.MetricsLogger;
import com.android.keyguard.KeyguardStatusView;
-import com.android.systemui.AutoReinflateContainer;
-import com.android.systemui.AutoReinflateContainer.InflateListener;
import com.android.systemui.DejankUtils;
import com.android.systemui.EventLogConstants;
import com.android.systemui.EventLogTags;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.classifier.FalsingManager;
-import com.android.systemui.plugins.qs.QSContainer;
+import com.android.systemui.fragments.FragmentHostManager;
+import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
+import com.android.systemui.plugins.qs.QS;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.ExpandableView;
import com.android.systemui.statusbar.FlingAnimationUtils;
@@ -70,7 +72,7 @@
ExpandableView.OnHeightChangedListener,
View.OnClickListener, NotificationStackScrollLayout.OnOverscrollTopChangedListener,
KeyguardAffordanceHelper.Callback, NotificationStackScrollLayout.OnEmptySpaceClickListener,
- HeadsUpManager.OnHeadsUpChangedListener, QSContainer.HeightListener {
+ HeadsUpManager.OnHeadsUpChangedListener, QS.HeightListener {
private static final boolean DEBUG = false;
@@ -92,8 +94,8 @@
private KeyguardAffordanceHelper mAfforanceHelper;
private KeyguardUserSwitcher mKeyguardUserSwitcher;
private KeyguardStatusBarView mKeyguardStatusBar;
- protected QSContainer mQsContainer;
- private AutoReinflateContainer mQsAutoReinflateContainer;
+ private QS mQs;
+ private FrameLayout mQsFrame;
private KeyguardStatusView mKeyguardStatusView;
private TextView mClockView;
private View mReserveNotificationSpace;
@@ -236,31 +238,19 @@
mKeyguardBottomArea.setAffordanceHelper(mAfforanceHelper);
mLastOrientation = getResources().getConfiguration().orientation;
- mQsAutoReinflateContainer =
- (AutoReinflateContainer) findViewById(R.id.qs_auto_reinflate_container);
- mQsAutoReinflateContainer.addInflateListener(new InflateListener() {
- @Override
- public void onInflated(View v) {
- mQsContainer = (QSContainer) v.findViewById(R.id.quick_settings_container);
- mQsContainer.setPanelView(NotificationPanelView.this);
- mQsContainer.getHeader().getExpandView()
- .setOnClickListener(NotificationPanelView.this);
+ mQsFrame = (FrameLayout) findViewById(R.id.qs_frame);
+ }
- // recompute internal state when qspanel height changes
- mQsContainer.addOnLayoutChangeListener(new OnLayoutChangeListener() {
- @Override
- public void onLayoutChange(View v, int left, int top, int right, int bottom,
- int oldLeft, int oldTop, int oldRight, int oldBottom) {
- final int height = bottom - top;
- final int oldHeight = oldBottom - oldTop;
- if (height != oldHeight) {
- onQsHeightChanged();
- }
- }
- });
- mNotificationStackScroller.setQsContainer(mQsContainer);
- }
- });
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ FragmentHostManager.get(this).addTagListener(QS.TAG, mFragmentListener);
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ FragmentHostManager.get(this).removeTagListener(QS.TAG, mFragmentListener);
}
@Override
@@ -288,12 +278,12 @@
int panelWidth = getResources().getDimensionPixelSize(R.dimen.notification_panel_width);
int panelGravity = getResources().getInteger(R.integer.notification_panel_layout_gravity);
FrameLayout.LayoutParams lp =
- (FrameLayout.LayoutParams) mQsAutoReinflateContainer.getLayoutParams();
+ (FrameLayout.LayoutParams) mQsFrame.getLayoutParams();
if (lp.width != panelWidth) {
lp.width = panelWidth;
lp.gravity = panelGravity;
- mQsAutoReinflateContainer.setLayoutParams(lp);
- mQsContainer.post(mUpdateHeader);
+ mQsFrame.setLayoutParams(lp);
+ mQs.getView().post(mUpdateHeader);
}
lp = (FrameLayout.LayoutParams) mNotificationStackScroller.getLayoutParams();
@@ -314,8 +304,10 @@
// Calculate quick setting heights.
int oldMaxHeight = mQsMaxExpansionHeight;
- mQsMinExpansionHeight = mKeyguardShowing ? 0 : mQsContainer.getQsMinExpansionHeight();
- mQsMaxExpansionHeight = mQsContainer.getDesiredHeight();
+ if (mQs != null) {
+ mQsMinExpansionHeight = mKeyguardShowing ? 0 : mQs.getQsMinExpansionHeight();
+ mQsMaxExpansionHeight = mQs.getDesiredHeight();
+ }
positionClockAndNotifications();
if (mQsExpanded && mQsFullyExpanded) {
mQsExpansionHeight = mQsMaxExpansionHeight;
@@ -337,8 +329,8 @@
// 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());
+ if (mQsSizeChangeAnimator == null && mQs != null) {
+ mQs.setHeightOverride(mQs.getDesiredHeight());
}
updateMaxHeadsUpTranslation();
}
@@ -357,7 +349,7 @@
requestScrollerTopPaddingUpdate(false /* animate */);
requestPanelHeightUpdate();
int height = (int) mQsSizeChangeAnimator.getAnimatedValue();
- mQsContainer.setHeightOverride(height);
+ mQs.setHeightOverride(height);
}
});
mQsSizeChangeAnimator.addListener(new AnimatorListenerAdapter() {
@@ -377,7 +369,7 @@
boolean animate = mNotificationStackScroller.isAddOrRemoveAnimationPending();
int stackScrollerPadding;
if (mStatusBarState != StatusBarState.KEYGUARD) {
- stackScrollerPadding = mQsContainer.getHeader().getHeight() + mQsPeekHeight;
+ stackScrollerPadding = (mQs != null ? mQs.getHeader().getHeight() : 0) + mQsPeekHeight;
mTopPaddingAdjustment = 0;
} else {
mClockPositionAlgorithm.setup(
@@ -490,7 +482,8 @@
public void setQsExpansionEnabled(boolean qsExpansionEnabled) {
mQsExpansionEnabled = qsExpansionEnabled;
- mQsContainer.setHeaderClickable(qsExpansionEnabled);
+ if (mQs == null) return;
+ mQs.setHeaderClickable(qsExpansionEnabled);
}
@Override
@@ -571,7 +564,7 @@
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
- if (mBlockTouches || mQsContainer.isCustomizing()) {
+ if (mBlockTouches || mQs.isCustomizing()) {
return false;
}
initDownStates(event);
@@ -731,7 +724,7 @@
@Override
public boolean onTouchEvent(MotionEvent event) {
- if (mBlockTouches || mQsContainer.isCustomizing()) {
+ if (mBlockTouches || (mQs != null && mQs.isCustomizing())) {
return false;
}
initDownStates(event);
@@ -804,10 +797,10 @@
}
private boolean isInQsArea(float x, float y) {
- return (x >= mQsAutoReinflateContainer.getX()
- && x <= mQsAutoReinflateContainer.getX() + mQsAutoReinflateContainer.getWidth())
+ return (x >= mQsFrame.getX()
+ && x <= mQsFrame.getX() + mQsFrame.getWidth())
&& (y <= mNotificationStackScroller.getBottomMostNotificationBottom()
- || y <= mQsContainer.getY() + mQsContainer.getHeight());
+ || y <= mQs.getView().getY() + mQs.getView().getHeight());
}
private boolean isOpenQsEvent(MotionEvent event) {
@@ -962,7 +955,8 @@
private void setOverScrolling(boolean overscrolling) {
mStackScrollerOverscrolling = overscrolling;
- mQsContainer.setOverscrolling(overscrolling);
+ if (mQs == null) return;
+ mQs.setOverscrolling(overscrolling);
}
private void onQsExpansionStarted() {
@@ -1000,24 +994,28 @@
mStatusBarState = statusBarState;
mKeyguardShowing = keyguardShowing;
- mQsContainer.setKeyguardShowing(mKeyguardShowing);
+ if (mQs != null) {
+ mQs.setKeyguardShowing(mKeyguardShowing);
+ }
if (oldState == StatusBarState.KEYGUARD
&& (goingToFullShade || statusBarState == StatusBarState.SHADE_LOCKED)) {
animateKeyguardStatusBarOut();
long delay = mStatusBarState == StatusBarState.SHADE_LOCKED
? 0 : mStatusBar.calculateGoingToFullShadeDelay();
- mQsContainer.animateHeaderSlidingIn(delay);
+ mQs.animateHeaderSlidingIn(delay);
} else if (oldState == StatusBarState.SHADE_LOCKED
&& statusBarState == StatusBarState.KEYGUARD) {
animateKeyguardStatusBarIn(StackStateAnimator.ANIMATION_DURATION_STANDARD);
- mQsContainer.animateHeaderSlidingOut();
+ mQs.animateHeaderSlidingOut();
} else {
mKeyguardStatusBar.setAlpha(1f);
mKeyguardStatusBar.setVisibility(keyguardShowing ? View.VISIBLE : View.INVISIBLE);
if (keyguardShowing && oldState != mStatusBarState) {
mKeyguardBottomArea.onKeyguardShowingChanged();
- mQsContainer.hideImmediately();
+ if (mQs != null) {
+ mQs.hideImmediately();
+ }
}
}
if (keyguardShowing) {
@@ -1163,7 +1161,6 @@
}
private void updateQsState() {
- mQsContainer.setExpanded(mQsExpanded);
mNotificationStackScroller.setQsExpanded(mQsExpanded);
mNotificationStackScroller.setScrollingEnabled(
mStatusBarState != StatusBarState.KEYGUARD && (!mQsExpanded
@@ -1176,6 +1173,8 @@
if (mKeyguardUserSwitcher != null && mQsExpanded && !mStackScrollerOverscrolling) {
mKeyguardUserSwitcher.hideIfNotSimple(true /* animate */);
}
+ if (mQs == null) return;
+ mQs.setExpanded(mQsExpanded);
}
private void setQsExpansion(float height) {
@@ -1222,11 +1221,12 @@
}
protected void updateQsExpansion() {
- mQsContainer.setQsExpansion(getQsExpansionFraction(), getHeaderTranslation());
+ if (mQs == null) return;
+ mQs.setQsExpansion(getQsExpansionFraction(), getHeaderTranslation());
}
private String getKeyguardOrLockScreenString() {
- if (mQsContainer.isCustomizing()) {
+ if (mQs.isCustomizing()) {
return getContext().getString(R.string.accessibility_desc_quick_settings_edit);
} else if (mStatusBarState == StatusBarState.KEYGUARD) {
return getContext().getString(R.string.accessibility_desc_lock_screen);
@@ -1357,9 +1357,9 @@
if (!mQsExpansionEnabled || mCollapsedOnDown) {
return false;
}
- View header = mKeyguardShowing ? mKeyguardStatusBar : mQsContainer.getHeader();
- boolean onHeader = x >= mQsAutoReinflateContainer.getX()
- && x <= mQsAutoReinflateContainer.getX() + mQsAutoReinflateContainer.getWidth()
+ View header = mKeyguardShowing ? mKeyguardStatusBar : mQs.getHeader();
+ final boolean onHeader = x >= mQsFrame.getX()
+ && x <= mQsFrame.getX() + mQsFrame.getWidth()
&& y >= header.getTop() && y <= header.getBottom();
if (mQsExpanded) {
return onHeader || (yDiff < 0 && isInQsArea(x, y));
@@ -1621,7 +1621,7 @@
}
// Since there are QS tiles in the header now, we need to make sure we start listening
// immediately so they can be up to date.
- mQsContainer.setHeaderListening(true);
+ mQs.setHeaderListening(true);
}
@Override
@@ -1659,8 +1659,9 @@
}
private void setListening(boolean listening) {
- mQsContainer.setListening(listening);
mKeyguardStatusBar.setListening(listening);
+ if (mQs == null) return;
+ mQs.setListening(listening);
}
@Override
@@ -1748,7 +1749,7 @@
}
public void onQsHeightChanged() {
- mQsMaxExpansionHeight = mQsContainer.getDesiredHeight();
+ mQsMaxExpansionHeight = mQs.getDesiredHeight();
if (mQsExpanded && mQsFullyExpanded) {
mQsExpansionHeight = mQsMaxExpansionHeight;
requestScrollerTopPaddingUpdate(false /* animate */);
@@ -2018,11 +2019,11 @@
}
public boolean isQsDetailShowing() {
- return mQsContainer.isShowingDetail();
+ return mQs.isShowingDetail();
}
public void closeQsDetail() {
- mQsContainer.closeDetail();
+ mQs.closeDetail();
}
@Override
@@ -2110,7 +2111,7 @@
private final Runnable mUpdateHeader = new Runnable() {
@Override
public void run() {
- mQsContainer.getHeader().updateEverything();
+ mQs.getHeader().updateEverything();
}
};
@@ -2257,7 +2258,7 @@
protected void setVerticalPanelTranslation(float translation) {
mNotificationStackScroller.setTranslationX(translation);
- mQsAutoReinflateContainer.setTranslationX(translation);
+ mQsFrame.setTranslationX(translation);
}
protected void updateExpandedHeight(float expandedHeight) {
@@ -2355,4 +2356,38 @@
public void setGroupManager(NotificationGroupManager groupManager) {
mGroupManager = groupManager;
}
+
+ private final FragmentListener mFragmentListener = new FragmentListener() {
+ @Override
+ public void onFragmentViewCreated(String tag, Fragment fragment) {
+ mQs = (QS) fragment;
+ mQs.setPanelView(NotificationPanelView.this);
+ mQs.getHeader().getExpandView().setOnClickListener(NotificationPanelView.this);
+ mQs.setHeaderClickable(mQsExpansionEnabled);
+ mQs.setKeyguardShowing(mKeyguardShowing);
+ mQs.setOverscrolling(mStackScrollerOverscrolling);
+
+ // recompute internal state when qspanel height changes
+ mQs.getView().addOnLayoutChangeListener(
+ (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
+ final int height = bottom - top;
+ final int oldHeight = oldBottom - oldTop;
+ if (height != oldHeight) {
+ onQsHeightChanged();
+ }
+ });
+ mNotificationStackScroller.setQsContainer((ViewGroup) mQs.getView());
+ updateQsExpansion();
+ }
+
+ @Override
+ public void onFragmentViewDestroyed(String tag, Fragment fragment) {
+ // Manual handling of fragment lifecycle is only required because this bridges
+ // non-fragment and fragment code. Once we are using a fragment for the notification
+ // panel, mQs will not need to be null cause it will be tied to the same lifecycle.
+ if (fragment == mQs) {
+ mQs = null;
+ }
+ }
+ };
}
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 8b1fcd6..c85584e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.phone;
+import android.app.Fragment;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Canvas;
@@ -25,18 +26,17 @@
import android.view.WindowInsets;
import android.widget.FrameLayout;
-import com.android.systemui.AutoReinflateContainer;
import com.android.systemui.R;
-import com.android.systemui.plugins.qs.QSContainer;
+import com.android.systemui.fragments.FragmentHostManager;
+import com.android.systemui.plugins.qs.QS;
/**
* The container with notification stack scroller and quick settings inside.
*/
public class NotificationsQuickSettingsContainer extends FrameLayout
- implements ViewStub.OnInflateListener, AutoReinflateContainer.InflateListener {
+ implements ViewStub.OnInflateListener, FragmentHostManager.FragmentListener {
-
- private AutoReinflateContainer mQsContainer;
+ private FrameLayout mQsFrame;
private View mUserSwitcher;
private View mStackScroller;
private View mKeyguardStatusBar;
@@ -54,8 +54,7 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mQsContainer = (AutoReinflateContainer) findViewById(R.id.qs_auto_reinflate_container);
- mQsContainer.addInflateListener(this);
+ mQsFrame = (FrameLayout) findViewById(R.id.qs_frame);
mStackScroller = findViewById(R.id.notification_stack_scroller);
mStackScrollerMargin = ((LayoutParams) mStackScroller.getLayoutParams()).bottomMargin;
mKeyguardStatusBar = findViewById(R.id.keyguard_header);
@@ -65,9 +64,21 @@
}
@Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ FragmentHostManager.get(this).addTagListener(QS.TAG, this);
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ FragmentHostManager.get(this).removeTagListener(QS.TAG, this);
+ }
+
+ @Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
- reloadWidth(mQsContainer);
+ reloadWidth(mQsFrame);
reloadWidth(mStackScroller);
}
@@ -91,11 +102,11 @@
boolean statusBarVisible = mKeyguardStatusBar.getVisibility() == View.VISIBLE;
final boolean qsBottom = mQsExpanded && !mCustomizerAnimating;
- View stackQsTop = qsBottom ? mStackScroller : mQsContainer;
- View stackQsBottom = !qsBottom ? mStackScroller : mQsContainer;
+ View stackQsTop = qsBottom ? mStackScroller : mQsFrame;
+ View stackQsBottom = !qsBottom ? mStackScroller : mQsFrame;
// 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) {
+ if (child == mQsFrame) {
return super.drawChild(canvas, userSwitcherVisible && statusBarVisible ? mUserSwitcher
: statusBarVisible ? mKeyguardStatusBar
: userSwitcherVisible ? mUserSwitcher
@@ -129,8 +140,8 @@
}
@Override
- public void onInflated(View v) {
- QSContainer container = (QSContainer) v;
+ public void onFragmentViewCreated(String tag, Fragment fragment) {
+ QS container = (QS) fragment;
container.setContainer(this);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 0f7ad59..197fe24 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -141,11 +141,13 @@
import com.android.systemui.classifier.FalsingManager;
import com.android.systemui.doze.DozeHost;
import com.android.systemui.doze.DozeLog;
+import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.keyguard.KeyguardViewMediator;
-import com.android.systemui.plugins.qs.QSContainer.ActivityStarter;
-import com.android.systemui.plugins.qs.QSContainer.BaseStatusBarHeader;
-import com.android.systemui.plugins.qs.QSContainer;
+import com.android.systemui.plugins.qs.QS;
+import com.android.systemui.plugins.qs.QS.ActivityStarter;
+import com.android.systemui.plugins.qs.QS.BaseStatusBarHeader;
import com.android.systemui.qs.QSContainerImpl;
+import com.android.systemui.qs.QSFragment;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.recents.ScreenPinningRequest;
import com.android.systemui.recents.events.EventBus;
@@ -923,9 +925,12 @@
}
// Set up the quick settings tile panel
- AutoReinflateContainer container = (AutoReinflateContainer) mStatusBarWindow.findViewById(
- R.id.qs_auto_reinflate_container);
+ View container = mStatusBarWindow.findViewById(R.id.qs_frame);
if (container != null) {
+ FragmentHostManager fragmentHostManager = FragmentHostManager.get(container);
+ fragmentHostManager.getFragmentManager().beginTransaction()
+ .replace(R.id.qs_frame, new QSFragment(), QS.TAG)
+ .commit();
final QSTileHost qsh = SystemUIFactory.getInstance().createQSTileHost(mContext, this,
mBluetoothController, mLocationController, mRotationLockController,
mNetworkController, mZenModeController, mHotspotController,
@@ -934,21 +939,17 @@
mSecurityController, mBatteryController, mIconController,
mNextAlarmController);
mBrightnessMirrorController = new BrightnessMirrorController(mStatusBarWindow);
- container.addInflateListener(new InflateListener() {
- @Override
- public void onInflated(View v) {
- QSContainer qsContainer = (QSContainer) v.findViewById(
- R.id.quick_settings_container);
- if (qsContainer instanceof QSContainerImpl) {
- ((QSContainerImpl) qsContainer).setHost(qsh);
- mQSPanel = ((QSContainerImpl) qsContainer).getQsPanel();
- mQSPanel.setBrightnessMirror(mBrightnessMirrorController);
- mKeyguardStatusBar.setQSPanel(mQSPanel);
- }
- mHeader = qsContainer.getHeader();
- initSignalCluster(mHeader);
- mHeader.setActivityStarter(PhoneStatusBar.this);
+ fragmentHostManager.addTagListener(QS.TAG, (tag, f) -> {
+ QS qs = (QS) f;
+ if (qs instanceof QSFragment) {
+ ((QSFragment) qs).setHost(qsh);
+ mQSPanel = ((QSFragment) qs).getQsPanel();
+ mQSPanel.setBrightnessMirror(mBrightnessMirrorController);
+ mKeyguardStatusBar.setQSPanel(mQSPanel);
}
+ mHeader = qs.getHeader();
+ initSignalCluster(mHeader);
+ mHeader.setActivityStarter(PhoneStatusBar.this);
});
}
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 65c6347..657e9eb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
@@ -37,10 +37,10 @@
import com.android.keyguard.KeyguardStatusView;
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
-import com.android.systemui.plugins.qs.QSContainer.ActivityStarter;
-import com.android.systemui.plugins.qs.QSContainer.BaseStatusBarHeader;
+import com.android.systemui.plugins.qs.QS.ActivityStarter;
+import com.android.systemui.plugins.qs.QS.BaseStatusBarHeader;
import com.android.systemui.qs.QSPanel;
-import com.android.systemui.plugins.qs.QSContainer.Callback;
+import com.android.systemui.plugins.qs.QS.Callback;
import com.android.systemui.qs.QuickQSPanel;
import com.android.systemui.qs.TouchAnimator;
import com.android.systemui.qs.TouchAnimator.Builder;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index eda46c5..640f0d4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -55,9 +55,9 @@
import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.SystemUISecondaryUserService;
-import com.android.systemui.plugins.qs.QSContainer.DetailAdapter;
+import com.android.systemui.plugins.qs.QS.DetailAdapter;
import com.android.systemui.qs.tiles.UserDetailView;
-import com.android.systemui.plugins.qs.QSContainer.ActivityStarter;
+import com.android.systemui.plugins.qs.QS.ActivityStarter;
import com.android.systemui.statusbar.phone.SystemUIDialog;
import java.io.FileDescriptor;