Find a background to animate when launching a dialog or activity

This CL makes the launch animations a bit more robust by trying to find
a background in the View that is expanded into the activity/dialog
instead of just taking the View background (that can sometimes be null).

See b/222668708#comment1 and #comment2 for before/after videos.

Bug: 222668708
Test: Manual
Change-Id: I590b6d77a7c9b29a73f37e1f8072643cc8c0bcfa
This commit is contained in:
Jordan Demeulenaere
2022-03-04 14:01:59 +01:00
parent f89f27e005
commit 23653cfd20

View File

@@ -33,6 +33,7 @@ import android.view.ViewGroup
import android.view.ViewGroupOverlay
import android.widget.FrameLayout
import com.android.internal.jank.InteractionJankMonitor
import java.util.LinkedList
import kotlin.math.min
private const val TAG = "GhostedViewLaunchAnimatorController"
@@ -81,21 +82,51 @@ open class GhostedViewLaunchAnimatorController(
* [backgroundView].
*/
private var backgroundDrawable: WrappedDrawable? = null
private val backgroundInsets by lazy { getBackground()?.opticalInsets ?: Insets.NONE }
private val backgroundInsets by lazy { background?.opticalInsets ?: Insets.NONE }
private var startBackgroundAlpha: Int = 0xFF
private val ghostedViewLocation = IntArray(2)
private val ghostedViewState = LaunchAnimator.State()
/**
* Return the background of the [ghostedView]. This background will be used to draw the
* background of the background view that is expanding up to the final animation position. This
* is called at the start of the animation.
* The background of the [ghostedView]. This background will be used to draw the background of
* the background view that is expanding up to the final animation position.
*
* Note that during the animation, the alpha value value of this background will be set to 0,
* then set back to its initial value at the end of the animation.
*/
protected open fun getBackground(): Drawable? = ghostedView.background
private val background: Drawable?
init {
/** Find the first view with a background in [view] and its children. */
fun findBackground(view: View): Drawable? {
if (view.background != null) {
return view.background
}
// Perform a BFS to find the largest View with background.
val views = LinkedList<View>().apply {
add(view)
}
while (views.isNotEmpty()) {
val v = views.removeFirst()
if (v.background != null) {
return v.background
}
if (v is ViewGroup) {
for (i in 0 until v.childCount) {
views.add(v.getChildAt(i))
}
}
}
return null
}
background = findBackground(ghostedView)
}
/**
* Set the corner radius of [background]. The background is the one that was returned by
@@ -113,7 +144,7 @@ open class GhostedViewLaunchAnimatorController(
/** Return the current top corner radius of the background. */
protected open fun getCurrentTopCornerRadius(): Float {
val drawable = getBackground() ?: return 0f
val drawable = background ?: return 0f
val gradient = findGradientDrawable(drawable) ?: return 0f
// TODO(b/184121838): Support more than symmetric top & bottom radius.
@@ -122,7 +153,7 @@ open class GhostedViewLaunchAnimatorController(
/** Return the current bottom corner radius of the background. */
protected open fun getCurrentBottomCornerRadius(): Float {
val drawable = getBackground() ?: return 0f
val drawable = background ?: return 0f
val gradient = findGradientDrawable(drawable) ?: return 0f
// TODO(b/184121838): Support more than symmetric top & bottom radius.
@@ -162,9 +193,8 @@ open class GhostedViewLaunchAnimatorController(
// We wrap the ghosted view background and use it to draw the expandable background. Its
// alpha will be set to 0 as soon as we start drawing the expanding background.
val drawable = getBackground()
startBackgroundAlpha = drawable?.alpha ?: 0xFF
backgroundDrawable = WrappedDrawable(drawable)
startBackgroundAlpha = background?.alpha ?: 0xFF
backgroundDrawable = WrappedDrawable(background)
backgroundView?.background = backgroundDrawable
// Create a ghost of the view that will be moving and fading out. This allows to fade out