Allow updating the flyout message
Add functions to allow updating the contents of the flyout while it is either expanding or fully expanded. Flag: com.android.wm.shell.enable_bubble_bar Bug: 277815200 Test: atest BubbleBarFlyoutControllerTest Change-Id: Iea3fc7df792e02605df6b44c1da39e267f6d9d43
This commit is contained in:
+53
-22
@@ -72,32 +72,63 @@ constructor(
|
||||
lp.marginEnd = horizontalMargin
|
||||
container.addView(flyout, lp)
|
||||
|
||||
this.flyout = flyout
|
||||
flyout.showFromCollapsed(message) { showFlyout(AnimationType.COLLAPSE, onEnd) }
|
||||
}
|
||||
|
||||
private fun showFlyout(animationType: AnimationType, endAction: () -> Unit) {
|
||||
val flyout = this.flyout ?: return
|
||||
val animator = ValueAnimator.ofFloat(0f, 1f).setDuration(ANIMATION_DURATION_MS)
|
||||
animator.addUpdateListener { _ ->
|
||||
flyout.updateExpansionProgress(animator.animatedValue as Float)
|
||||
when (animationType) {
|
||||
AnimationType.FADE ->
|
||||
animator.addUpdateListener { _ -> flyout.alpha = animator.animatedValue as Float }
|
||||
AnimationType.COLLAPSE ->
|
||||
animator.addUpdateListener { _ ->
|
||||
flyout.updateExpansionProgress(animator.animatedValue as Float)
|
||||
}
|
||||
}
|
||||
animator.addListener(
|
||||
onStart = {
|
||||
val flyoutTop = flyout.top + flyout.translationY
|
||||
// If the top position of the flyout is negative, then it's bleeding over the
|
||||
// top boundary of its parent view
|
||||
if (flyoutTop < 0) callbacks.extendTopBoundary(space = -flyoutTop.toInt())
|
||||
},
|
||||
onStart = { extendTopBoundary() },
|
||||
onEnd = {
|
||||
onEnd()
|
||||
endAction()
|
||||
flyout.setOnClickListener { callbacks.flyoutClicked() }
|
||||
},
|
||||
)
|
||||
flyout.showFromCollapsed(message) { animator.start() }
|
||||
this.flyout = flyout
|
||||
animator.start()
|
||||
}
|
||||
|
||||
fun updateFlyoutFullyExpanded(message: BubbleBarFlyoutMessage, onEnd: () -> Unit) {
|
||||
val flyout = flyout ?: return
|
||||
hideFlyout(AnimationType.FADE) {
|
||||
flyout.updateData(message) { showFlyout(AnimationType.FADE, onEnd) }
|
||||
}
|
||||
}
|
||||
|
||||
fun updateFlyoutWhileExpanding(message: BubbleBarFlyoutMessage) {
|
||||
val flyout = flyout ?: return
|
||||
flyout.updateData(message) { extendTopBoundary() }
|
||||
}
|
||||
|
||||
private fun extendTopBoundary() {
|
||||
val flyout = flyout ?: return
|
||||
val flyoutTop = flyout.top + flyout.translationY
|
||||
// If the top position of the flyout is negative, then it's bleeding over the
|
||||
// top boundary of its parent view
|
||||
if (flyoutTop < 0) callbacks.extendTopBoundary(space = -flyoutTop.toInt())
|
||||
}
|
||||
|
||||
fun cancelFlyout(endAction: () -> Unit) {
|
||||
hideFlyout(AnimationType.FADE, endAction)
|
||||
hideFlyout(AnimationType.FADE) {
|
||||
cleanupFlyoutView()
|
||||
endAction()
|
||||
}
|
||||
}
|
||||
|
||||
fun collapseFlyout(endAction: () -> Unit) {
|
||||
hideFlyout(AnimationType.COLLAPSE, endAction)
|
||||
hideFlyout(AnimationType.COLLAPSE) {
|
||||
cleanupFlyoutView()
|
||||
endAction()
|
||||
}
|
||||
}
|
||||
|
||||
private fun hideFlyout(animationType: AnimationType, endAction: () -> Unit) {
|
||||
@@ -112,15 +143,15 @@ constructor(
|
||||
flyout.updateExpansionProgress(animator.animatedValue as Float)
|
||||
}
|
||||
}
|
||||
animator.addListener(
|
||||
onStart = { flyout.setOnClickListener(null) },
|
||||
onEnd = {
|
||||
container.removeView(flyout)
|
||||
this@BubbleBarFlyoutController.flyout = null
|
||||
callbacks.resetTopBoundary()
|
||||
endAction()
|
||||
},
|
||||
)
|
||||
animator.addListener(onStart = { flyout.setOnClickListener(null) }, onEnd = { endAction() })
|
||||
animator.start()
|
||||
}
|
||||
|
||||
private fun cleanupFlyoutView() {
|
||||
container.removeView(flyout)
|
||||
this@BubbleBarFlyoutController.flyout = null
|
||||
callbacks.resetTopBoundary()
|
||||
}
|
||||
|
||||
fun hasFlyout() = flyout != null
|
||||
}
|
||||
|
||||
@@ -198,6 +198,8 @@ class BubbleBarFlyoutView(
|
||||
} else {
|
||||
-positioner.distanceToCollapsedPosition.x
|
||||
}
|
||||
// TODO: b/277815200 - before collapsing, recalculate translationToCollapsedPosition because
|
||||
// the collapsed position may have changed
|
||||
val tyToCollapsedPosition =
|
||||
positioner.distanceToCollapsedPosition.y + triangleHeight - triangleOverlap
|
||||
translationToCollapsedPosition = PointF(txToCollapsedPosition, tyToCollapsedPosition)
|
||||
@@ -217,6 +219,12 @@ class BubbleBarFlyoutView(
|
||||
scheduler.runAfterLayout(expandAnimation)
|
||||
}
|
||||
|
||||
/** Updates the content of the flyout and schedules [afterLayout] to run after a layout pass. */
|
||||
fun updateData(flyoutMessage: BubbleBarFlyoutMessage, afterLayout: () -> Unit) {
|
||||
setData(flyoutMessage)
|
||||
scheduler.runAfterLayout(afterLayout)
|
||||
}
|
||||
|
||||
private fun setData(flyoutMessage: BubbleBarFlyoutMessage) {
|
||||
if (flyoutMessage.icon != null) {
|
||||
icon.visibility = VISIBLE
|
||||
|
||||
+57
@@ -115,11 +115,13 @@ class BubbleBarFlyoutControllerTest {
|
||||
fun hideFlyout_removedFromContainer() {
|
||||
InstrumentationRegistry.getInstrumentation().runOnMainSync {
|
||||
flyoutController.setUpAndShowFlyout(flyoutMessage) {}
|
||||
assertThat(flyoutController.hasFlyout()).isTrue()
|
||||
assertThat(flyoutContainer.childCount).isEqualTo(1)
|
||||
flyoutController.collapseFlyout {}
|
||||
animatorTestRule.advanceTimeBy(300)
|
||||
}
|
||||
assertThat(flyoutContainer.childCount).isEqualTo(0)
|
||||
assertThat(flyoutController.hasFlyout()).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -189,6 +191,61 @@ class BubbleBarFlyoutControllerTest {
|
||||
assertThat(flyoutCallbacks.flyoutClicked).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun updateFlyoutWhileExpanding() {
|
||||
InstrumentationRegistry.getInstrumentation().runOnMainSync {
|
||||
flyoutController.setUpAndShowFlyout(flyoutMessage) {}
|
||||
assertThat(flyoutController.hasFlyout()).isTrue()
|
||||
val flyout = flyoutContainer.findViewById<View>(R.id.bubble_bar_flyout_view)
|
||||
assertThat(flyout.findViewById<TextView>(R.id.bubble_flyout_text).text)
|
||||
.isEqualTo("message")
|
||||
// advance the animation about halfway
|
||||
animatorTestRule.advanceTimeBy(100)
|
||||
}
|
||||
assertThat(flyoutController.hasFlyout()).isTrue()
|
||||
|
||||
val newFlyoutMessage = flyoutMessage.copy(message = "new message")
|
||||
InstrumentationRegistry.getInstrumentation().runOnMainSync {
|
||||
val flyout = flyoutContainer.findViewById<View>(R.id.bubble_bar_flyout_view)
|
||||
// set negative translation to verify that the top boundary extends as a result of
|
||||
// updating while expanding
|
||||
flyout.translationY = -50f
|
||||
flyoutController.updateFlyoutWhileExpanding(newFlyoutMessage)
|
||||
assertThat(flyout.findViewById<TextView>(R.id.bubble_flyout_text).text)
|
||||
.isEqualTo("new message")
|
||||
}
|
||||
assertThat(flyoutCallbacks.topBoundaryExtendedSpace).isEqualTo(50)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun updateFlyoutFullyExpanded() {
|
||||
InstrumentationRegistry.getInstrumentation().runOnMainSync {
|
||||
flyoutController.setUpAndShowFlyout(flyoutMessage) {}
|
||||
animatorTestRule.advanceTimeBy(300)
|
||||
}
|
||||
assertThat(flyoutController.hasFlyout()).isTrue()
|
||||
|
||||
val newFlyoutMessage = flyoutMessage.copy(message = "new message")
|
||||
InstrumentationRegistry.getInstrumentation().runOnMainSync {
|
||||
val flyout = flyoutContainer.findViewById<View>(R.id.bubble_bar_flyout_view)
|
||||
// set negative translation to verify that the top boundary extends as a result of
|
||||
// updating while fully expanded
|
||||
flyout.translationY = -50f
|
||||
flyoutController.updateFlyoutFullyExpanded(newFlyoutMessage) {}
|
||||
|
||||
// advance the timer so that the fade out animation plays
|
||||
animatorTestRule.advanceTimeBy(250)
|
||||
assertThat(flyout.alpha).isEqualTo(0)
|
||||
assertThat(flyout.findViewById<TextView>(R.id.bubble_flyout_text).text)
|
||||
.isEqualTo("new message")
|
||||
|
||||
// advance the timer so that the fade in animation plays
|
||||
animatorTestRule.advanceTimeBy(250)
|
||||
assertThat(flyout.alpha).isEqualTo(1)
|
||||
}
|
||||
assertThat(flyoutCallbacks.topBoundaryExtendedSpace).isEqualTo(50)
|
||||
}
|
||||
|
||||
class FakeFlyoutCallbacks : FlyoutCallbacks {
|
||||
|
||||
var topBoundaryExtendedSpace = 0
|
||||
|
||||
Reference in New Issue
Block a user