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
This commit is contained in:
dshivangi
2023-04-11 17:00:48 +01:00
committed by Shivangi Dubey
parent 644791aae4
commit 3c18f4418d
2 changed files with 117 additions and 22 deletions

View File

@@ -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
)
}
}
}

View File

@@ -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<TransitionProgressListener>
private var xTranslationMax = 0f
@Before
@@ -73,10 +76,13 @@ class NotificationPanelUnfoldAnimationControllerTest : SysuiTestCase() {
statusBarStateController,
progressProvider
)
whenever(parent.findViewById<ViewGroup>(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<View>(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<View>(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<View>(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<View>(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<View>(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<View>(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() }
}
}