Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 00f62acc authored by Giulio Fiscella's avatar Giulio Fiscella Committed by Android (Google) Code Review
Browse files

Merge "Allow ViewHierarchyAnimator to exclude child views from animations." into udc-qpr-dev

parents 956c4a26 b072e53b
Loading
Loading
Loading
Loading
+34 −8
Original line number Diff line number Diff line
@@ -70,6 +70,9 @@ 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.
         *
         * The animator continues to respond to layout changes until [stopAnimating] is called.
         *
         * Successive calls to this method override the previous settings ([interpolator] and
@@ -82,9 +85,16 @@ class ViewHierarchyAnimator {
        fun animate(
            rootView: View,
            interpolator: Interpolator = DEFAULT_INTERPOLATOR,
            duration: Long = DEFAULT_DURATION
            duration: Long = DEFAULT_DURATION,
            excludedViews: Set<View> = emptySet()
        ): Boolean {
            return animate(rootView, interpolator, duration, ephemeral = false)
            return animate(
                rootView,
                interpolator,
                duration,
                ephemeral = false,
                excludedViews = excludedViews
            )
        }

        /**
@@ -95,16 +105,24 @@ class ViewHierarchyAnimator {
        fun animateNextUpdate(
            rootView: View,
            interpolator: Interpolator = DEFAULT_INTERPOLATOR,
            duration: Long = DEFAULT_DURATION
            duration: Long = DEFAULT_DURATION,
            excludedViews: Set<View> = emptySet()
        ): Boolean {
            return animate(rootView, interpolator, duration, ephemeral = true)
            return animate(
                rootView,
                interpolator,
                duration,
                ephemeral = true,
                excludedViews = excludedViews
            )
        }

        private fun animate(
            rootView: View,
            interpolator: Interpolator,
            duration: Long,
            ephemeral: Boolean
            ephemeral: Boolean,
            excludedViews: Set<View> = emptySet()
        ): Boolean {
            if (
                !occupiesSpace(
@@ -119,7 +137,7 @@ class ViewHierarchyAnimator {
            }

            val listener = createUpdateListener(interpolator, duration, ephemeral)
            addListener(rootView, listener, recursive = true)
            addListener(rootView, listener, recursive = true, excludedViews = excludedViews)
            return true
        }

@@ -921,8 +939,11 @@ class ViewHierarchyAnimator {
        private fun addListener(
            view: View,
            listener: View.OnLayoutChangeListener,
            recursive: Boolean = false
            recursive: Boolean = false,
            excludedViews: Set<View> = emptySet()
        ) {
            if (excludedViews.contains(view)) return

            // Make sure that only one listener is active at a time.
            val previousListener = view.getTag(R.id.tag_layout_listener)
            if (previousListener != null && previousListener is View.OnLayoutChangeListener) {
@@ -933,7 +954,12 @@ class ViewHierarchyAnimator {
            view.setTag(R.id.tag_layout_listener, listener)
            if (view is ViewGroup && recursive) {
                for (i in 0 until view.childCount) {
                    addListener(view.getChildAt(i), listener, recursive = true)
                    addListener(
                        view.getChildAt(i),
                        listener,
                        recursive = true,
                        excludedViews = excludedViews
                    )
                }
            }
        }
+36 −2
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@ import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.RelativeLayout
import androidx.test.filters.SmallTest
import com.android.app.animation.Interpolators
import com.android.systemui.SysuiTestCase
import com.android.systemui.util.children
import junit.framework.Assert.assertEquals
@@ -19,7 +20,6 @@ import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import com.android.app.animation.Interpolators

@SmallTest
@RunWith(AndroidTestingRunner::class)
@@ -178,7 +178,7 @@ ViewHierarchyAnimatorTest : SysuiTestCase() {
    }

    @Test
    fun animatesRootAndChildren() {
    fun animatesRootAndChildren_withoutExcludedViews() {
        setUpRootWithChildren()

        val success = ViewHierarchyAnimator.animate(rootView)
@@ -207,6 +207,40 @@ ViewHierarchyAnimatorTest : SysuiTestCase() {
        checkBounds(rootView.getChildAt(1), l = 95, t = 0, r = 190, b = 100)
    }

    @Test
    fun animatesRootAndChildren_withExcludedViews() {
        setUpRootWithChildren()

        val success = ViewHierarchyAnimator.animate(
            rootView,
            excludedViews = setOf(rootView.getChildAt(0))
        )
        // 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))
        assertNotNull(rootView.getChildAt(1).getTag(R.id.tag_animator))
        // The initial values for the affected views should be those of the previous layout, while
        // the excluded view 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 = 100, t = 0, r = 200, 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 */)