Fix some entrance animations for new QSHeaders

* Use qsVisible to indicate whether the shade is visible and the header
should be shown.
* When in lockscreen, use
LockscreenShadeTransitionController#dragProgress to track shade
expansion.
* Use this shade expansion to fade out the KeyguardStatusBarView

Test: manual, with and without flag, handheld and split shade
Test: atest SystemUITests
Bug: 202847414
Change-Id: Id57adff2fd75eba86832e8790816ef2d9afcf83d
This commit is contained in:
Fabian Kozynski
2021-11-10 12:20:07 -05:00
parent 3555ebc8b5
commit 3cd40e0641
7 changed files with 123 additions and 24 deletions

View File

@@ -23,11 +23,22 @@
app:constraintSetEnd="@id/qs_header_constraint"
app:constraintSetStart="@id/qqs_header_constraint">
<KeyFrameSet>
<!-- These positions are to prevent visual movement of @id/date -->
<KeyPosition
app:keyPositionType="pathRelative"
app:percentX="0"
app:framePosition="50"
app:framePosition="49"
app:motionTarget="@id/date" />
<KeyPosition
app:keyPositionType="pathRelative"
app:percentX="1"
app:framePosition="51"
app:motionTarget="@id/date" />
<KeyAttribute
app:motionTarget="@id/date"
app:framePosition="50"
android:alpha="0"
/>
</KeyFrameSet>
</Transition>

View File

@@ -298,8 +298,8 @@ class LockscreenShadeTransitionController @Inject constructor(
nsslController.setTransitionToFullShadeAmount(field)
notificationPanelController.setTransitionToFullShadeAmount(field,
false /* animate */, 0 /* delay */)
val progress = MathUtils.saturate(dragDownAmount / scrimTransitionDistance)
qS.setTransitionToFullShadeAmount(field, progress)
dragProgress = MathUtils.saturate(dragDownAmount / scrimTransitionDistance)
qS.setTransitionToFullShadeAmount(field, dragProgress)
// TODO: appear media also in split shade
val mediaAmount = if (useSplitShade) 0f else field
mediaHierarchyManager.setTransitionToFullShadeAmount(mediaAmount)
@@ -308,6 +308,9 @@ class LockscreenShadeTransitionController @Inject constructor(
}
}
var dragProgress = 0f
private set
private fun transitionToShadeAmountCommon(dragDownAmount: Float) {
val scrimProgress = MathUtils.saturate(dragDownAmount / scrimTransitionDistance)
scrimController.setTransitionToFullShadeProgress(scrimProgress)

View File

@@ -392,7 +392,7 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat
}
float alphaQsExpansion = 1 - Math.min(
1, mNotificationPanelViewStateProvider.getQsExpansionFraction() * 2);
1, mNotificationPanelViewStateProvider.getLockscreenShadeDragProgress() * 2);
float newAlpha = Math.min(getKeyguardContentsAlpha(), alphaQsExpansion)
* mKeyguardStatusBarAnimateAlpha
* (1.0f - mKeyguardHeadsUpShowingAmount);

View File

@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.phone;
import static android.view.View.GONE;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static androidx.constraintlayout.widget.ConstraintSet.END;
import static androidx.constraintlayout.widget.ConstraintSet.PARENT_ID;
@@ -33,7 +34,6 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_N
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
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 com.android.systemui.statusbar.notification.stack.StackStateAnimator.ANIMATION_DURATION_FOLD_TO_AOD;
import static com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManagerKt.STATE_CLOSED;
@@ -466,6 +466,9 @@ public class NotificationPanelViewController extends PanelViewController {
private boolean mIsFullWidth;
private boolean mBlockingExpansionForCurrentTouch;
// TODO (b/204204226): no longer needed once refactor is complete
private final boolean mUseCombinedQSHeaders;
/**
* Following variables maintain state of events when input focus transfer may occur.
*/
@@ -913,6 +916,8 @@ public class NotificationPanelViewController extends PanelViewController {
mQsFrameTranslateController = qsFrameTranslateController;
updateUserSwitcherFlags();
onFinishInflate();
mUseCombinedQSHeaders = featureFlags.isEnabled(Flags.COMBINED_QS_HEADERS);
}
private void onFinishInflate() {
@@ -1142,6 +1147,9 @@ public class NotificationPanelViewController extends PanelViewController {
} else {
constraintSet.connect(R.id.qs_frame, END, PARENT_ID, END);
constraintSet.connect(R.id.notification_stack_scroller, START, PARENT_ID, START);
if (mUseCombinedQSHeaders) {
constraintSet.constrainHeight(R.id.split_shade_status_bar, WRAP_CONTENT);
}
}
constraintSet.getConstraint(R.id.notification_stack_scroller).layout.mWidth = panelWidth;
constraintSet.getConstraint(R.id.qs_frame).layout.mWidth = qsWidth;
@@ -1392,7 +1400,6 @@ public class NotificationPanelViewController extends PanelViewController {
stackScrollerPadding = mClockPositionResult.stackScrollerPaddingExpanded;
}
mSplitShadeHeaderController.setShadeExpandedFraction(getExpandedFraction());
mNotificationStackScrollLayoutController.setIntrinsicPadding(stackScrollerPadding);
mKeyguardBottomArea.setAntiBurnInOffsetX(mClockPositionResult.clockX);
@@ -2401,7 +2408,6 @@ public class NotificationPanelViewController extends PanelViewController {
? 1f : computeQsExpansionFraction();
mQs.setQsExpansion(adjustedExpansionFraction, getExpandedFraction(), getHeaderTranslation(),
squishiness);
mSplitShadeHeaderController.setQsExpandedFraction(qsExpansionFraction);
mMediaHierarchyManager.setQsExpansion(qsExpansionFraction);
int qsPanelBottomY = calculateQsBottomPosition(qsExpansionFraction);
mScrimController.setQsPosition(qsExpansionFraction, qsPanelBottomY);
@@ -2415,6 +2421,17 @@ public class NotificationPanelViewController extends PanelViewController {
mDepthController.setQsPanelExpansion(qsExpansionFraction);
// updateQsExpansion will get called whenever mTransitionToFullShadeProgress or
// mLockscreenShadeTransitionController.getDragProgress change.
// When in lockscreen, getDragProgress indicates the true expanded fraction of QS
float shadeExpandedFraction = mTransitioningToFullShadeProgress > 0
? mLockscreenShadeTransitionController.getDragProgress()
: getExpandedFraction();
mSplitShadeHeaderController.setShadeExpandedFraction(shadeExpandedFraction);
mSplitShadeHeaderController.setQsExpandedFraction(qsExpansionFraction);
mSplitShadeHeaderController.setShadeExpanded(mQsVisible);
if (mCommunalViewController != null) {
mCommunalViewController.updateQsExpansion(qsExpansionFraction);
}
@@ -3629,11 +3646,15 @@ public class NotificationPanelViewController extends PanelViewController {
return !isFullWidth() || !mShowIconsWhenExpanded;
}
public final QS.ScrollListener mScrollListener = scrollY -> {
if (scrollY > 0 && !mQsFullyExpanded) {
if (DEBUG) Log.d(TAG, "Scrolling while not expanded. Forcing expand");
// If we are scrolling QS, we should be fully expanded.
expandWithQs();
public final QS.ScrollListener mScrollListener = new QS.ScrollListener() {
@Override
public void onQsPanelScrollChanged(int scrollY) {
mSplitShadeHeaderController.setQsScrollY(scrollY);
if (scrollY > 0 && !mQsFullyExpanded) {
if (DEBUG) Log.d(TAG, "Scrolling while not expanded. Forcing expand");
// If we are scrolling QS, we should be fully expanded.
expandWithQs();
}
}
};
@@ -4684,8 +4705,6 @@ public class NotificationPanelViewController extends PanelViewController {
// would reset
maybeAnimateBottomAreaAlpha();
updateQsState();
mSplitShadeHeaderController.setShadeExpanded(
mBarState == SHADE || mBarState == SHADE_LOCKED);
}
@Override
@@ -4715,6 +4734,9 @@ public class NotificationPanelViewController extends PanelViewController {
* {@link KeyguardStatusBarViewController} and remove this method.
*/
boolean shouldHeadsUpBeVisible();
/** Return the fraction of the shade that's expanded, when in lockscreen. */
float getLockscreenShadeDragProgress();
}
private final NotificationPanelViewStateProvider mNotificationPanelViewStateProvider =
@@ -4733,6 +4755,11 @@ public class NotificationPanelViewController extends PanelViewController {
public boolean shouldHeadsUpBeVisible() {
return mHeadsUpAppearanceController.shouldBeVisible();
}
@Override
public float getLockscreenShadeDragProgress() {
return mLockscreenShadeTransitionController.getDragProgress();
}
};
/**

View File

@@ -24,6 +24,7 @@ import com.android.systemui.R
import com.android.systemui.animation.ShadeInterpolation
import com.android.systemui.battery.BatteryMeterView
import com.android.systemui.battery.BatteryMeterViewController
import com.android.systemui.dump.DumpManager
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.qs.ChipVisibilityListener
@@ -32,6 +33,8 @@ import com.android.systemui.qs.carrier.QSCarrierGroupController
import com.android.systemui.statusbar.phone.dagger.StatusBarComponent.StatusBarScope
import com.android.systemui.statusbar.phone.dagger.StatusBarViewModule.SPLIT_SHADE_BATTERY_CONTROLLER
import com.android.systemui.statusbar.phone.dagger.StatusBarViewModule.SPLIT_SHADE_HEADER
import java.io.FileDescriptor
import java.io.PrintWriter
import javax.inject.Inject
import javax.inject.Named
@@ -42,12 +45,23 @@ class SplitShadeHeaderController @Inject constructor(
private val privacyIconsController: HeaderPrivacyIconsController,
qsCarrierGroupControllerBuilder: QSCarrierGroupController.Builder,
featureFlags: FeatureFlags,
@Named(SPLIT_SHADE_BATTERY_CONTROLLER) batteryMeterViewController: BatteryMeterViewController
) {
@Named(SPLIT_SHADE_BATTERY_CONTROLLER) batteryMeterViewController: BatteryMeterViewController,
dumpManager: DumpManager
) : Dumpable {
companion object {
private val HEADER_TRANSITION_ID = R.id.header_transition
private val SPLIT_HEADER_TRANSITION_ID = R.id.split_header_transition
private val QQS_HEADER_CONSTRAINT = R.id.qqs_header_constraint
private val QS_HEADER_CONSTRAINT = R.id.qs_header_constraint
private val SPLIT_HEADER_CONSTRAINT = R.id.split_header_constraint
private fun Int.stateToString() = when (this) {
QQS_HEADER_CONSTRAINT -> "QQS Header"
QS_HEADER_CONSTRAINT -> "QS Header"
SPLIT_HEADER_CONSTRAINT -> "Split Header"
else -> "Unknown state"
}
}
private val combinedHeaders = featureFlags.isEnabled(Flags.COMBINED_QS_HEADERS)
@@ -99,14 +113,22 @@ class SplitShadeHeaderController @Inject constructor(
}
}
var qsScrollY = 0
set(value) {
if (field != value) {
field = value
updateScrollY()
}
}
private val chipVisibilityListener: ChipVisibilityListener = object : ChipVisibilityListener {
override fun onChipVisibilityRefreshed(visible: Boolean) {
if (statusBar is MotionLayout) {
val state = statusBar.getConstraintSet(R.id.qqs_header_constraint).apply {
val state = statusBar.getConstraintSet(QQS_HEADER_CONSTRAINT).apply {
setAlpha(R.id.statusIcons, if (visible) 0f else 1f)
setAlpha(R.id.batteryRemainingIcon, if (visible) 0f else 1f)
}
statusBar.updateState(R.id.qqs_header_constraint, state)
statusBar.updateState(QQS_HEADER_CONSTRAINT, state)
}
}
}
@@ -115,11 +137,11 @@ class SplitShadeHeaderController @Inject constructor(
if (statusBar is MotionLayout) {
val context = statusBar.context
val resources = statusBar.resources
statusBar.getConstraintSet(R.id.qqs_header_constraint)
statusBar.getConstraintSet(QQS_HEADER_CONSTRAINT)
.load(context, resources.getXml(R.xml.qqs_header))
statusBar.getConstraintSet(R.id.qs_header_constraint)
statusBar.getConstraintSet(QS_HEADER_CONSTRAINT)
.load(context, resources.getXml(R.xml.qs_header))
statusBar.getConstraintSet(R.id.split_header_constraint)
statusBar.getConstraintSet(SPLIT_HEADER_CONSTRAINT)
.load(context, resources.getXml(R.xml.split_header))
privacyIconsController.chipVisibilityListener = chipVisibilityListener
}
@@ -149,10 +171,19 @@ class SplitShadeHeaderController @Inject constructor(
qsCarrierGroupController = qsCarrierGroupControllerBuilder
.setQSCarrierGroup(statusBar.findViewById(R.id.carrier_group))
.build()
dumpManager.registerDumpable(this)
updateVisibility()
updateConstraints()
}
private fun updateScrollY() {
if (!splitShadeMode && combinedHeaders) {
statusBar.scrollY = qsScrollY
}
}
private fun onShadeExpandedChanged() {
if (shadeExpanded) {
privacyIconsController.startListening()
@@ -198,6 +229,7 @@ class SplitShadeHeaderController @Inject constructor(
statusBar.setTransition(HEADER_TRANSITION_ID)
statusBar.transitionToStart()
updatePosition()
updateScrollY()
}
}
@@ -226,4 +258,17 @@ class SplitShadeHeaderController @Inject constructor(
iconContainer.addIgnoredSlots(carrierIconSlots)
}
}
override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
pw.println("visible: $visible")
pw.println("shadeExpanded: $shadeExpanded")
pw.println("shadeExpandedFraction: $shadeExpandedFraction")
pw.println("splitShadeMode: $splitShadeMode")
pw.println("qsExpandedFraction: $qsExpandedFraction")
pw.println("qsScrollY: $qsScrollY")
if (combinedHeaders) {
statusBar as MotionLayout
pw.println("currentState: ${statusBar.currentState.stateToString()}")
}
}
}

View File

@@ -278,11 +278,11 @@ public class KeyguardStatusBarViewControllerTest extends SysuiTestCase {
}
@Test
public void updateViewState_qsExpansionOne_viewHidden() {
public void updateViewState_dragProgressOne_viewHidden() {
mController.onViewAttached();
updateStateToKeyguard();
mNotificationPanelViewStateProvider.setQsExpansionFraction(1f);
mNotificationPanelViewStateProvider.setLockscreenShadeDragProgress(1f);
mController.updateViewState();
@@ -356,6 +356,7 @@ public class KeyguardStatusBarViewControllerTest extends SysuiTestCase {
private float mPanelViewExpandedHeight = 100f;
private float mQsExpansionFraction = 0f;
private boolean mShouldHeadsUpBeVisible = false;
private float mLockscreenShadeDragProgress = 0f;
@Override
public float getPanelViewExpandedHeight() {
@@ -372,6 +373,11 @@ public class KeyguardStatusBarViewControllerTest extends SysuiTestCase {
return mShouldHeadsUpBeVisible;
}
@Override
public float getLockscreenShadeDragProgress() {
return mLockscreenShadeDragProgress;
}
public void setPanelViewExpandedHeight(float panelViewExpandedHeight) {
this.mPanelViewExpandedHeight = panelViewExpandedHeight;
}
@@ -383,5 +389,9 @@ public class KeyguardStatusBarViewControllerTest extends SysuiTestCase {
public void setShouldHeadsUpBeVisible(boolean shouldHeadsUpBeVisible) {
this.mShouldHeadsUpBeVisible = shouldHeadsUpBeVisible;
}
public void setLockscreenShadeDragProgress(float lockscreenShadeDragProgress) {
this.mLockscreenShadeDragProgress = lockscreenShadeDragProgress;
}
}
}

View File

@@ -8,6 +8,7 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.ShadeInterpolation
import com.android.systemui.battery.BatteryMeterView
import com.android.systemui.battery.BatteryMeterViewController
import com.android.systemui.dump.DumpManager
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.qs.HeaderPrivacyIconsController
@@ -37,6 +38,7 @@ class SplitShadeHeaderControllerTest : SysuiTestCase() {
@Mock private lateinit var batteryMeterView: BatteryMeterView
@Mock private lateinit var batteryMeterViewController: BatteryMeterViewController
@Mock private lateinit var privacyIconsController: HeaderPrivacyIconsController
@Mock private lateinit var dumpManager: DumpManager
@JvmField @Rule val mockitoRule = MockitoJUnit.rule()
var viewVisibility = View.GONE
@@ -66,7 +68,8 @@ class SplitShadeHeaderControllerTest : SysuiTestCase() {
privacyIconsController,
qsCarrierGroupControllerBuilder,
featureFlags,
batteryMeterViewController
batteryMeterViewController,
dumpManager
)
carrierIconSlots = listOf(
context.getString(com.android.internal.R.string.status_bar_mobile))