summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt23
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt34
2 files changed, 53 insertions, 4 deletions
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt
index bd3706e1aff3..00d905652987 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt
@@ -70,8 +70,10 @@ class ViewHierarchyAnimator {
* If a new layout change happens while an animation is already in progress, the animation
* is updated to continue from the current values to the new end state.
*
- * A set of [excludedViews] can be passed. If any dependent view from [rootView] matches an
- * entry in this set, changes to that view will not be animated.
+ * By default, child views whole layout changes are animated as well. However, this can be
+ * controlled by [animateChildren]. If children are included, a set of [excludedViews] can
+ * be passed. If any dependent view from [rootView] matches an entry in this set, changes to
+ * that view will not be animated.
*
* The animator continues to respond to layout changes until [stopAnimating] is called.
*
@@ -86,6 +88,7 @@ class ViewHierarchyAnimator {
rootView: View,
interpolator: Interpolator = DEFAULT_INTERPOLATOR,
duration: Long = DEFAULT_DURATION,
+ animateChildren: Boolean = true,
excludedViews: Set<View> = emptySet()
): Boolean {
return animate(
@@ -93,6 +96,7 @@ class ViewHierarchyAnimator {
interpolator,
duration,
ephemeral = false,
+ animateChildren = animateChildren,
excludedViews = excludedViews
)
}
@@ -106,6 +110,7 @@ class ViewHierarchyAnimator {
rootView: View,
interpolator: Interpolator = DEFAULT_INTERPOLATOR,
duration: Long = DEFAULT_DURATION,
+ animateChildren: Boolean = true,
excludedViews: Set<View> = emptySet()
): Boolean {
return animate(
@@ -113,6 +118,7 @@ class ViewHierarchyAnimator {
interpolator,
duration,
ephemeral = true,
+ animateChildren = animateChildren,
excludedViews = excludedViews
)
}
@@ -122,6 +128,7 @@ class ViewHierarchyAnimator {
interpolator: Interpolator,
duration: Long,
ephemeral: Boolean,
+ animateChildren: Boolean,
excludedViews: Set<View> = emptySet()
): Boolean {
if (
@@ -137,7 +144,13 @@ class ViewHierarchyAnimator {
}
val listener = createUpdateListener(interpolator, duration, ephemeral)
- addListener(rootView, listener, recursive = true, excludedViews = excludedViews)
+ addListener(
+ rootView,
+ listener,
+ recursive = true,
+ animateChildren = animateChildren,
+ excludedViews = excludedViews
+ )
return true
}
@@ -940,6 +953,7 @@ class ViewHierarchyAnimator {
view: View,
listener: View.OnLayoutChangeListener,
recursive: Boolean = false,
+ animateChildren: Boolean = true,
excludedViews: Set<View> = emptySet()
) {
if (excludedViews.contains(view)) return
@@ -952,12 +966,13 @@ class ViewHierarchyAnimator {
view.addOnLayoutChangeListener(listener)
view.setTag(R.id.tag_layout_listener, listener)
- if (view is ViewGroup && recursive) {
+ if (animateChildren && view is ViewGroup && recursive) {
for (i in 0 until view.childCount) {
addListener(
view.getChildAt(i),
listener,
recursive = true,
+ animateChildren = animateChildren,
excludedViews = excludedViews
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt
index 212dad78d5b2..c2e6db362035 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt
@@ -242,6 +242,40 @@ ViewHierarchyAnimatorTest : SysuiTestCase() {
}
@Test
+ fun animatesRootOnly() {
+ setUpRootWithChildren()
+
+ val success = ViewHierarchyAnimator.animate(
+ rootView,
+ animateChildren = false
+ )
+ // Change all bounds.
+ rootView.measure(
+ View.MeasureSpec.makeMeasureSpec(180, View.MeasureSpec.EXACTLY),
+ View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY)
+ )
+ rootView.layout(10 /* l */, 20 /* t */, 200 /* r */, 120 /* b */)
+
+ assertTrue(success)
+ assertNotNull(rootView.getTag(R.id.tag_animator))
+ assertNull(rootView.getChildAt(0).getTag(R.id.tag_animator))
+ assertNull(rootView.getChildAt(1).getTag(R.id.tag_animator))
+ // The initial values for the root view should be those of the previous layout, while the
+ // children views should be at the final values from the beginning.
+ checkBounds(rootView, l = 0, t = 0, r = 200, b = 100)
+ checkBounds(rootView.getChildAt(0), l = 0, t = 0, r = 90, b = 100)
+ checkBounds(rootView.getChildAt(1), l = 90, t = 0, r = 180, b = 100)
+ endAnimation(rootView)
+ assertNull(rootView.getTag(R.id.tag_animator))
+ assertNull(rootView.getChildAt(0).getTag(R.id.tag_animator))
+ assertNull(rootView.getChildAt(1).getTag(R.id.tag_animator))
+ // The end values should be those of the latest layout.
+ checkBounds(rootView, l = 10, t = 20, r = 200, b = 120)
+ checkBounds(rootView.getChildAt(0), l = 0, t = 0, r = 90, b = 100)
+ checkBounds(rootView.getChildAt(1), l = 90, t = 0, r = 180, b = 100)
+ }
+
+ @Test
fun animatesInvisibleViews() {
rootView.layout(10 /* l */, 10 /* t */, 50 /* r */, 50 /* b */)
rootView.visibility = View.INVISIBLE