Extracting status bar from quick settings in split shade

First phase of moving status bar from quick settings to upper layer so status bar takes full width of the screen.
This change:
- hides status bar in quick settings and adjusts all paddings/margins
- reuses QS status bar as a full width status bar <- this will be fixed in following CLs
- creates controller for new status bar, which manages its (dis)appearing <- alpha/shift revealing animation TODO

Bug: 182981830
Test: manual (automated coming in next CLs if this approach looks good)
Change-Id: I84adf101d050ccbd286bc02808a9ad93aeda2039
This commit is contained in:
Michal Brzezinski
2021-07-06 13:40:43 +01:00
parent 45613c7bdb
commit 28110ae6ba
13 changed files with 124 additions and 45 deletions

View File

@@ -21,4 +21,8 @@
<!-- Overload default clock widget parameters -->
<dimen name="widget_big_font_size">88dp</dimen>
<dimen name="qs_header_system_icons_area_height">0dp</dimen>
<dimen name="qs_panel_padding_top">0dp</dimen>
</resources>

View File

@@ -19,7 +19,7 @@
<View
android:id="@+id/customizer_transparent_view"
android:layout_width="match_parent"
android:layout_height="@*android:dimen/quick_qs_offset_height"
android:layout_height="@dimen/qs_header_system_icons_area_height"
android:background="@android:color/transparent" />
<com.android.keyguard.AlphaOptimizedLinearLayout

View File

@@ -42,21 +42,21 @@
android:layout_gravity="top"
android:clipChildren="false"
android:clipToPadding="false">
<!-- Time, icons and Carrier (only in QS) -->
<include layout="@layout/quick_qs_status_icons"/>
<!-- Time, icons and Carrier (only in QS) -->
<include layout="@layout/quick_qs_status_icons"/>
<com.android.systemui.qs.QuickQSPanel
android:id="@+id/quick_qs_panel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/quick_qs_status_icons"
android:layout_marginTop="@dimen/qqs_layout_margin_top"
android:accessibilityTraversalAfter="@id/quick_qs_status_icons"
android:clipChildren="false"
android:clipToPadding="false"
android:focusable="true"
android:paddingBottom="10dp"
android:importantForAccessibility="yes" />
<com.android.systemui.qs.QuickQSPanel
android:id="@+id/quick_qs_panel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/quick_qs_status_icons"
android:layout_marginTop="@dimen/qqs_layout_margin_top"
android:accessibilityTraversalAfter="@id/quick_qs_status_icons"
android:clipChildren="false"
android:clipToPadding="false"
android:focusable="true"
android:paddingBottom="10dp"
android:importantForAccessibility="yes" />
</RelativeLayout>
</com.android.systemui.qs.QuickStatusBarHeader>

View File

@@ -64,6 +64,8 @@
android:clipToPadding="false"
android:clipChildren="false">
<include layout="@layout/quick_qs_status_icons"/>
<include
layout="@layout/keyguard_status_view"
android:visibility="gone"/>

View File

@@ -402,8 +402,11 @@
<dimen name="status_bar_header_padding_bottom">48dp</dimen>
<!-- The height of the container that holds the battery and time in the quick settings header.
Preferred over using "@*android:dimen/quick_qs_offset_height" as system icons are not always
present in quick settings (e.g. in split shade) and it's useful to be able to override this
value in such cases.
-->
<dimen name="qs_header_system_icons_area_height">48dp</dimen>
<dimen name="qs_header_system_icons_area_height">@*android:dimen/quick_qs_offset_height</dimen>
<!-- How far the quick-quick settings panel extends below the status bar -->
<dimen name="qs_quick_header_panel_height">128dp</dimen>
@@ -455,6 +458,9 @@
<!-- Width for the notification panel and related windows -->
<dimen name="match_parent">-1px</dimen>
<!-- Height of status bar in split shade mode - visible only on large screens -->
<dimen name="split_shade_status_bar_height">@*android:dimen/quick_qs_offset_height</dimen>
<!-- The top margin of the panel that holds the list of notifications. -->
<dimen name="notification_panel_margin_top">0dp</dimen>

View File

@@ -160,8 +160,8 @@ public class QSContainerImpl extends FrameLayout {
QuickStatusBarHeaderController quickStatusBarHeaderController) {
mQSPanelContainer.setPaddingRelative(
getPaddingStart(),
mContext.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.quick_qs_offset_height),
mContext.getResources()
.getDimensionPixelSize(R.dimen.qs_header_system_icons_area_height),
getPaddingEnd(),
getPaddingBottom()
);

View File

@@ -57,9 +57,8 @@ public class QuickStatusBarHeader extends FrameLayout {
protected QuickQSPanel mHeaderQsPanel;
private View mDatePrivacyView;
private View mDateView;
private View mSecurityHeaderView;
private View mClockIconsView;
private View mStatusIconsView;
private View mContainer;
private View mQSCarriers;
@@ -82,7 +81,6 @@ public class QuickStatusBarHeader extends FrameLayout {
private int mWaterfallTopInset;
private int mCutOutPaddingLeft;
private int mCutOutPaddingRight;
private float mViewAlpha = 1.0f;
private float mKeyguardExpansionFraction;
private int mTextColorPrimary = Color.TRANSPARENT;
private int mTopViewMeasureHeight;
@@ -115,12 +113,11 @@ public class QuickStatusBarHeader extends FrameLayout {
mHeaderQsPanel = findViewById(R.id.quick_qs_panel);
mDatePrivacyView = findViewById(R.id.quick_status_bar_date_privacy);
mClockIconsView = findViewById(R.id.quick_qs_status_icons);
mStatusIconsView = findViewById(R.id.quick_qs_status_icons);
mQSCarriers = findViewById(R.id.carrier_group);
mContainer = findViewById(R.id.qs_container);
mIconContainer = findViewById(R.id.statusIcons);
mPrivacyChip = findViewById(R.id.privacy_chip);
mDateView = findViewById(R.id.date);
mSecurityHeaderView = findViewById(R.id.header_text_container);
mClockIconsSeparator = findViewById(R.id.separator);
mRightLayout = findViewById(R.id.rightLayout);
@@ -161,10 +158,6 @@ public class QuickStatusBarHeader extends FrameLayout {
updateAnimators();
}
public QuickQSPanel getHeaderQsPanel() {
return mHeaderQsPanel;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
@@ -201,6 +194,11 @@ public class QuickStatusBarHeader extends FrameLayout {
void updateResources() {
Resources resources = mContext.getResources();
// status bar is already displayed out of QS in split shade
boolean shouldUseSplitShade =
resources.getBoolean(R.bool.config_use_split_notification_shade);
mStatusIconsView.setVisibility(shouldUseSplitShade ? View.GONE : View.VISIBLE);
mDatePrivacyView.setVisibility(shouldUseSplitShade ? View.GONE : View.VISIBLE);
mRoundedCornerPadding = resources.getDimensionPixelSize(
R.dimen.rounded_corner_content_padding);
@@ -212,13 +210,13 @@ public class QuickStatusBarHeader extends FrameLayout {
Math.max(qsOffsetHeight, mDatePrivacyView.getMinimumHeight());
mDatePrivacyView.setLayoutParams(mDatePrivacyView.getLayoutParams());
mClockIconsView.getLayoutParams().height =
Math.max(qsOffsetHeight, mClockIconsView.getMinimumHeight());
mClockIconsView.setLayoutParams(mClockIconsView.getLayoutParams());
mStatusIconsView.getLayoutParams().height =
Math.max(qsOffsetHeight, mStatusIconsView.getMinimumHeight());
mStatusIconsView.setLayoutParams(mStatusIconsView.getLayoutParams());
ViewGroup.LayoutParams lp = getLayoutParams();
if (mQsDisabled) {
lp.height = mClockIconsView.getLayoutParams().height;
lp.height = mStatusIconsView.getLayoutParams().height;
} else {
lp.height = WRAP_CONTENT;
}
@@ -364,7 +362,7 @@ public class QuickStatusBarHeader extends FrameLayout {
if (disabled == mQsDisabled) return;
mQsDisabled = disabled;
mHeaderQsPanel.setDisabledByPolicy(disabled);
mClockIconsView.setVisibility(mQsDisabled ? View.GONE : View.VISIBLE);
mStatusIconsView.setVisibility(mQsDisabled ? View.GONE : View.VISIBLE);
updateResources();
}
@@ -378,7 +376,7 @@ public class QuickStatusBarHeader extends FrameLayout {
StatusBarWindowView.paddingNeededForCutoutAndRoundedCorner(
cutout, cornerCutoutPadding, -1);
mDatePrivacyView.setPadding(padding.first, 0, padding.second, 0);
mClockIconsView.setPadding(padding.first, 0, padding.second, 0);
mStatusIconsView.setPadding(padding.first, 0, padding.second, 0);
LinearLayout.LayoutParams datePrivacySeparatorLayoutParams =
(LinearLayout.LayoutParams) mDatePrivacySeparator.getLayoutParams();
LinearLayout.LayoutParams mClockIconsSeparatorLayoutParams =
@@ -440,7 +438,7 @@ public class QuickStatusBarHeader extends FrameLayout {
private void updateHeadersPadding() {
setContentMargins(mDatePrivacyView, 0, 0);
setContentMargins(mClockIconsView, 0, 0);
setContentMargins(mStatusIconsView, 0, 0);
int paddingLeft = 0;
int paddingRight = 0;
@@ -466,7 +464,7 @@ public class QuickStatusBarHeader extends FrameLayout {
mWaterfallTopInset,
paddingRight,
0);
mClockIconsView.setPadding(paddingLeft,
mStatusIconsView.setPadding(paddingLeft,
mWaterfallTopInset,
paddingRight,
0);
@@ -493,7 +491,7 @@ public class QuickStatusBarHeader extends FrameLayout {
* @param scrollY the scroll of the QSPanel container
*/
public void setExpandedScrollAmount(int scrollY) {
mClockIconsView.setScrollY(scrollY);
mStatusIconsView.setScrollY(scrollY);
mDatePrivacyView.setScrollY(scrollY);
}
}

View File

@@ -84,8 +84,8 @@ public class QSCustomizer extends LinearLayout {
void updateResources() {
LayoutParams lp = (LayoutParams) mTransparentView.getLayoutParams();
lp.height = mContext.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.quick_qs_offset_height);
lp.height = mContext.getResources()
.getDimensionPixelSize(R.dimen.qs_header_system_icons_area_height);
mTransparentView.setLayoutParams(lp);
}

View File

@@ -21,6 +21,7 @@ import static android.view.View.GONE;
import static androidx.constraintlayout.widget.ConstraintSet.END;
import static androidx.constraintlayout.widget.ConstraintSet.PARENT_ID;
import static androidx.constraintlayout.widget.ConstraintSet.START;
import static androidx.constraintlayout.widget.ConstraintSet.TOP;
import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE;
import static com.android.keyguard.KeyguardClockSwitch.LARGE;
@@ -28,6 +29,8 @@ import static com.android.keyguard.KeyguardClockSwitch.SMALL;
import static com.android.systemui.classifier.Classifier.QS_COLLAPSE;
import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS;
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
import static com.android.systemui.statusbar.StatusBarState.SHADE;
import static com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED;
import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_ALL;
import static java.lang.Float.isNaN;
@@ -331,6 +334,7 @@ public class NotificationPanelViewController extends PanelViewController {
private final int mMaxKeyguardNotifications;
private final LockscreenShadeTransitionController mLockscreenShadeTransitionController;
private final TapAgainViewController mTapAgainViewController;
private final SplitShadeStatusBarController mSplitShadeStatusBarController;
private boolean mShouldUseSplitNotificationShade;
// Current max allowed keyguard notifications determined by measuring the panel
private int mMaxAllowedKeyguardNotifications;
@@ -393,7 +397,7 @@ public class NotificationPanelViewController extends PanelViewController {
private float mDownY;
private int mDisplayTopInset = 0; // in pixels
private int mDisplayRightInset = 0; // in pixels
private int mSplitShadeNotificationsTopPadding;
private int mSplitShadeStatusBarHeight;
private final KeyguardClockPositionAlgorithm
mClockPositionAlgorithm =
@@ -719,6 +723,7 @@ public class NotificationPanelViewController extends PanelViewController {
QuickAccessWalletController quickAccessWalletController,
@Main Executor uiExecutor,
SecureSettings secureSettings,
SplitShadeStatusBarController splitShadeStatusBarController,
UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
NotificationRemoteInputManager remoteInputManager) {
super(view, falsingManager, dozeLog, keyguardStateController,
@@ -752,6 +757,7 @@ public class NotificationPanelViewController extends PanelViewController {
mShouldUseSplitNotificationShade =
Utils.shouldUseSplitNotificationShade(mFeatureFlags, mResources);
mView.setWillNotDraw(!DEBUG);
mSplitShadeStatusBarController = splitShadeStatusBarController;
mLayoutInflater = layoutInflater;
mFalsingManager = falsingManager;
mFalsingCollector = falsingCollector;
@@ -1020,8 +1026,8 @@ public class NotificationPanelViewController extends PanelViewController {
public void updateResources() {
mQuickQsOffsetHeight = mResources.getDimensionPixelSize(
com.android.internal.R.dimen.quick_qs_offset_height);
mSplitShadeNotificationsTopPadding =
mResources.getDimensionPixelSize(R.dimen.notifications_top_padding_split_shade);
mSplitShadeStatusBarHeight =
mResources.getDimensionPixelSize(R.dimen.split_shade_status_bar_height);
int qsWidth = mResources.getDimensionPixelSize(R.dimen.qs_panel_width);
int panelWidth = mResources.getDimensionPixelSize(R.dimen.notification_panel_width);
mShouldUseSplitNotificationShade =
@@ -1030,6 +1036,11 @@ public class NotificationPanelViewController extends PanelViewController {
if (mQs != null) {
mQs.setTranslateWhileExpanding(mShouldUseSplitNotificationShade);
}
int topMargin = mShouldUseSplitNotificationShade ? mSplitShadeStatusBarHeight :
mResources.getDimensionPixelSize(R.dimen.notification_panel_margin_top);
mSplitShadeStatusBarController.setSplitShadeMode(mShouldUseSplitNotificationShade);
// To change the constraints at runtime, all children of the ConstraintLayout must have ids
ensureAllViewsHaveIds(mNotificationContainerParent);
ConstraintSet constraintSet = new ConstraintSet();
@@ -1048,6 +1059,8 @@ public class NotificationPanelViewController extends PanelViewController {
}
constraintSet.getConstraint(R.id.notification_stack_scroller).layout.mWidth = panelWidth;
constraintSet.getConstraint(R.id.qs_frame).layout.mWidth = qsWidth;
constraintSet.setMargin(R.id.notification_stack_scroller, TOP, topMargin);
constraintSet.setMargin(R.id.qs_frame, TOP, topMargin);
constraintSet.applyTo(mNotificationContainerParent);
updateKeyguardStatusViewAlignment(false /* animate */);
@@ -2333,8 +2346,8 @@ public class NotificationPanelViewController extends PanelViewController {
left = 0;
right = getView().getRight() + mDisplayRightInset;
} else {
top = Math.min(qsPanelBottomY, mSplitShadeNotificationsTopPadding);
bottom = mNotificationStackScrollLayoutController.getHeight();
top = Math.min(qsPanelBottomY, mSplitShadeStatusBarHeight);
bottom = top + mNotificationStackScrollLayoutController.getHeight();
left = mNotificationStackScrollLayoutController.getLeft();
right = mNotificationStackScrollLayoutController.getRight();
}
@@ -2432,7 +2445,7 @@ public class NotificationPanelViewController extends PanelViewController {
int nsslLeft = left - mNotificationStackScrollLayoutController.getLeft();
int nsslRight = right - mNotificationStackScrollLayoutController.getLeft();
int nsslTop = top - mNotificationStackScrollLayoutController.getTop();
int nsslBottom = bottom - mNotificationStackScrollLayoutController.getTop();
int nsslBottom = bottom;
int bottomRadius = mShouldUseSplitNotificationShade ? radius : 0;
mNotificationStackScrollLayoutController.setRoundedClippingBounds(
nsslLeft, nsslTop, nsslRight, nsslBottom, radius, bottomRadius);
@@ -2473,7 +2486,7 @@ public class NotificationPanelViewController extends PanelViewController {
private float calculateNotificationsTopPadding() {
if (mShouldUseSplitNotificationShade && !mKeyguardShowing) {
return mSplitShadeNotificationsTopPadding + mQsNotificationTopPadding;
return 0;
}
if (mKeyguardShowing && (mQsExpandImmediate
|| mIsExpanding && mQsExpandedWhenExpandingStarted)) {
@@ -4453,6 +4466,8 @@ public class NotificationPanelViewController extends PanelViewController {
maybeAnimateBottomAreaAlpha();
resetHorizontalPanelPosition();
updateQsState();
mSplitShadeStatusBarController.setShadeExpanded(
mBarState == SHADE || mBarState == SHADE_LOCKED);
}
@Override

View File

@@ -0,0 +1,29 @@
package com.android.systemui.statusbar.phone
import android.view.View
import com.android.systemui.statusbar.phone.dagger.StatusBarComponent.StatusBarScope
import com.android.systemui.statusbar.phone.dagger.StatusBarViewModule.SPLIT_SHADE_STATUS_BAR
import javax.inject.Inject
import javax.inject.Named
@StatusBarScope
class SplitShadeStatusBarController @Inject constructor(
@Named(SPLIT_SHADE_STATUS_BAR) val view: View
) {
var shadeExpanded = false
set(value) {
field = value
updateVisibility()
}
var splitShadeMode = false
set(value) {
field = value
updateVisibility()
}
private fun updateVisibility() {
view.visibility = if (shadeExpanded && splitShadeMode) View.VISIBLE else View.GONE
}
}

View File

@@ -23,6 +23,7 @@ import com.android.systemui.biometrics.AuthRippleController;
import com.android.systemui.statusbar.phone.NotificationPanelViewController;
import com.android.systemui.statusbar.phone.NotificationShadeWindowView;
import com.android.systemui.statusbar.phone.NotificationShadeWindowViewController;
import com.android.systemui.statusbar.phone.SplitShadeStatusBarController;
import com.android.systemui.statusbar.phone.StatusBarWindowController;
import java.lang.annotation.Documented;
@@ -86,4 +87,10 @@ public interface StatusBarComponent {
*/
@StatusBarScope
AuthRippleController getAuthRippleController();
/**
* Creates a SplitShadeStatusBarController.
*/
@StatusBarScope
SplitShadeStatusBarController getSplitShadeStatusBarController();
}

View File

@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.phone.dagger;
import android.annotation.Nullable;
import android.view.View;
import com.android.keyguard.LockIconView;
import com.android.systemui.R;
@@ -25,11 +26,16 @@ import com.android.systemui.statusbar.phone.NotificationPanelView;
import com.android.systemui.statusbar.phone.NotificationShadeWindowView;
import com.android.systemui.statusbar.phone.TapAgainView;
import javax.inject.Named;
import dagger.Module;
import dagger.Provides;
@Module
public abstract class StatusBarViewModule {
public static final String SPLIT_SHADE_STATUS_BAR = "split_shade_status_bar";
/** */
@Provides
@StatusBarComponent.StatusBarScope
@@ -55,6 +61,15 @@ public abstract class StatusBarViewModule {
return notificationShadeWindowView.findViewById(R.id.auth_ripple);
}
/** */
@Provides
@Named(SPLIT_SHADE_STATUS_BAR)
@StatusBarComponent.StatusBarScope
public static View getSlitShadeStatusBarView(
NotificationShadeWindowView notificationShadeWindowView) {
return notificationShadeWindowView.findViewById(R.id.quick_qs_status_icons);
}
/** */
@Provides
@StatusBarComponent.StatusBarScope

View File

@@ -283,6 +283,8 @@ public class NotificationPanelViewTest extends SysuiTestCase {
@Mock
private SecureSettings mSecureSettings;
@Mock
private SplitShadeStatusBarController mSplitShadeStatusBarController;
@Mock
private ContentResolver mContentResolver;
@Mock
private TapAgainViewController mTapAgainViewController;
@@ -438,6 +440,7 @@ public class NotificationPanelViewTest extends SysuiTestCase {
mQuickAccessWalletController,
new FakeExecutor(new FakeSystemClock()),
mSecureSettings,
mSplitShadeStatusBarController,
mUnlockedScreenOffAnimationController,
mNotificationRemoteInputManager);
mNotificationPanelViewController.initDependencies(