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:
@@ -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>
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -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()}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user