From 3c18f4418d9b4ebee8e6a749571a32a5df6ae83d Mon Sep 17 00:00:00 2001 From: dshivangi Date: Tue, 11 Apr 2023 17:00:48 +0100 Subject: [PATCH] Separated animation of status bar in split shade This change fixes the bug where date view from status bar of notification split shade is not animated while folding and unfolding is in progress. The root cause is that the incorrect date view is being animated due to multiple views with the same ID under the same parent ViewGroup(Split shade). Hence we separated the animation of the status bar of the split shade from other views in the split shade. This allowed us to use the split shade status bar as the parent ViewGroup to correctly register the date view for animation. Test: atest com.android.systemui.shade.NotificationPanelUnfoldAnimationControllerTest Test: functional test in a follow-up cl Fixes: 277214741 Change-Id: I27d33721b1c835a51587f3865898a1e8a48f3f3c --- ...ificationPanelUnfoldAnimationController.kt | 31 +++-- ...ationPanelUnfoldAnimationControllerTest.kt | 108 +++++++++++++++--- 2 files changed, 117 insertions(+), 22 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationController.kt b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationController.kt index b445000c467d0..5850a846eed6a 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationController.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationController.kt @@ -47,19 +47,36 @@ constructor( viewsIdToTranslate = setOf( ViewIdToTranslate(R.id.quick_settings_panel, START, filterShade), - ViewIdToTranslate(R.id.notification_stack_scroller, END, filterShade), - ViewIdToTranslate(R.id.statusIcons, END, filterShade), - ViewIdToTranslate(R.id.privacy_container, END, filterShade), - ViewIdToTranslate(R.id.batteryRemainingIcon, END, filterShade), - ViewIdToTranslate(R.id.carrier_group, END, filterShade), - ViewIdToTranslate(R.id.clock, START, filterShade), - ViewIdToTranslate(R.id.date, START, filterShade)), + ViewIdToTranslate(R.id.notification_stack_scroller, END, filterShade)), progressProvider = progressProvider) } + private val translateAnimatorStatusBar by lazy { + UnfoldConstantTranslateAnimator( + viewsIdToTranslate = + setOf( + ViewIdToTranslate(R.id.statusIcons, END, filterShade), + ViewIdToTranslate(R.id.privacy_container, END, filterShade), + ViewIdToTranslate(R.id.batteryRemainingIcon, END, filterShade), + ViewIdToTranslate(R.id.carrier_group, END, filterShade), + ViewIdToTranslate(R.id.clock, START, filterShade), + ViewIdToTranslate(R.id.date, START, filterShade) + ), + progressProvider = progressProvider + ) + } + fun setup(root: ViewGroup) { val translationMax = context.resources.getDimensionPixelSize(R.dimen.notification_side_paddings).toFloat() translateAnimator.init(root, translationMax) + val splitShadeStatusBarViewGroup: ViewGroup? = + root.findViewById(R.id.split_shade_status_bar) + if (splitShadeStatusBarViewGroup != null) { + translateAnimatorStatusBar.init( + splitShadeStatusBarViewGroup, + translationMax + ) + } } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationControllerTest.kt index db6fc136e6510..38a666eeb410c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationControllerTest.kt @@ -37,6 +37,7 @@ import org.junit.runner.RunWith import org.mockito.ArgumentCaptor import org.mockito.Captor import org.mockito.Mock +import org.mockito.Mockito.atLeastOnce import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @@ -54,10 +55,12 @@ class NotificationPanelUnfoldAnimationControllerTest : SysuiTestCase() { @Mock private lateinit var parent: ViewGroup + @Mock private lateinit var splitShadeStatusBar: ViewGroup + @Mock private lateinit var statusBarStateController: StatusBarStateController private lateinit var underTest: NotificationPanelUnfoldAnimationController - private lateinit var progressListener: TransitionProgressListener + private lateinit var progressListeners: List private var xTranslationMax = 0f @Before @@ -73,10 +76,13 @@ class NotificationPanelUnfoldAnimationControllerTest : SysuiTestCase() { statusBarStateController, progressProvider ) + whenever(parent.findViewById(R.id.split_shade_status_bar)).thenReturn( + splitShadeStatusBar + ) underTest.setup(parent) - verify(progressProvider).addCallback(capture(progressListenerCaptor)) - progressListener = progressListenerCaptor.value + verify(progressProvider, atLeastOnce()).addCallback(capture(progressListenerCaptor)) + progressListeners = progressListenerCaptor.allValues } @Test @@ -86,16 +92,16 @@ class NotificationPanelUnfoldAnimationControllerTest : SysuiTestCase() { val view = View(context) whenever(parent.findViewById(R.id.quick_settings_panel)).thenReturn(view) - progressListener.onTransitionStarted() + onTransitionStarted() assertThat(view.translationX).isZero() - progressListener.onTransitionProgress(0f) + onTransitionProgress(0f) assertThat(view.translationX).isZero() - progressListener.onTransitionProgress(0.5f) + onTransitionProgress(0.5f) assertThat(view.translationX).isZero() - progressListener.onTransitionFinished() + onTransitionFinished() assertThat(view.translationX).isZero() } @@ -106,16 +112,16 @@ class NotificationPanelUnfoldAnimationControllerTest : SysuiTestCase() { val view = View(context) whenever(parent.findViewById(R.id.quick_settings_panel)).thenReturn(view) - progressListener.onTransitionStarted() + onTransitionStarted() assertThat(view.translationX).isZero() - progressListener.onTransitionProgress(0f) + onTransitionProgress(0f) assertThat(view.translationX).isEqualTo(xTranslationMax) - progressListener.onTransitionProgress(0.5f) + onTransitionProgress(0.5f) assertThat(view.translationX).isEqualTo(0.5f * xTranslationMax) - progressListener.onTransitionFinished() + onTransitionFinished() assertThat(view.translationX).isZero() } @@ -126,16 +132,88 @@ class NotificationPanelUnfoldAnimationControllerTest : SysuiTestCase() { val view = View(context) whenever(parent.findViewById(R.id.quick_settings_panel)).thenReturn(view) - progressListener.onTransitionStarted() + onTransitionStarted() assertThat(view.translationX).isZero() - progressListener.onTransitionProgress(0f) + onTransitionProgress(0f) assertThat(view.translationX).isEqualTo(xTranslationMax) - progressListener.onTransitionProgress(0.5f) + onTransitionProgress(0.5f) assertThat(view.translationX).isEqualTo(0.5f * xTranslationMax) - progressListener.onTransitionFinished() + onTransitionFinished() assertThat(view.translationX).isZero() } + + @Test + fun whenInKeyguardState_statusBarViewDoesNotMove() { + whenever(statusBarStateController.getState()).thenReturn(KEYGUARD) + + val view = View(context) + whenever(splitShadeStatusBar.findViewById(R.id.date)).thenReturn(view) + + onTransitionStarted() + assertThat(view.translationX).isZero() + + onTransitionProgress(0f) + assertThat(view.translationX).isZero() + + onTransitionProgress(0.5f) + assertThat(view.translationX).isZero() + + onTransitionFinished() + assertThat(view.translationX).isZero() + } + + @Test + fun whenInShadeState_statusBarViewDoesMove() { + whenever(statusBarStateController.getState()).thenReturn(SHADE) + + val view = View(context) + whenever(splitShadeStatusBar.findViewById(R.id.date)).thenReturn(view) + + onTransitionStarted() + assertThat(view.translationX).isZero() + + onTransitionProgress(0f) + assertThat(view.translationX).isEqualTo(xTranslationMax) + + onTransitionProgress(0.5f) + assertThat(view.translationX).isEqualTo(0.5f * xTranslationMax) + + onTransitionFinished() + assertThat(view.translationX).isZero() + } + + @Test + fun whenInShadeLockedState_statusBarViewDoesMove() { + whenever(statusBarStateController.getState()).thenReturn(SHADE_LOCKED) + + val view = View(context) + whenever(splitShadeStatusBar.findViewById(R.id.date)).thenReturn(view) + onTransitionStarted() + assertThat(view.translationX).isZero() + + onTransitionProgress(0f) + assertThat(view.translationX).isEqualTo(xTranslationMax) + + onTransitionProgress(0.5f) + assertThat(view.translationX).isEqualTo(0.5f * xTranslationMax) + + onTransitionFinished() + assertThat(view.translationX).isZero() + } + + private fun onTransitionStarted() { + progressListeners.forEach { it.onTransitionStarted() } + } + + private fun onTransitionProgress(progress: Float) { + progressListeners.forEach { it.onTransitionProgress(progress) } + } + + private fun onTransitionFinished() { + progressListeners.forEach { it.onTransitionFinished() } + } + }