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

Commit 7565863c authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Making transitions between gone hosts work better" into rvc-dev am: acd4508f

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/11967243

Change-Id: I48d716371d6a5540caa6f70906ce3c43269bfdaa
parents 0e2ded82 acd4508f
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -48,5 +48,6 @@
        android:layout_height="48dp"
        android:layout_height="48dp"
        android:layout_marginBottom="4dp"
        android:layout_marginBottom="4dp"
        android:tint="@color/media_primary_text"
        android:tint="@color/media_primary_text"
        android:forceHasOverlappingRendering="false"
    />
    />
</FrameLayout>
</FrameLayout>
+1 −0
Original line number Original line Diff line number Diff line
@@ -24,6 +24,7 @@
    android:clipChildren="false"
    android:clipChildren="false"
    android:clipToPadding="false"
    android:clipToPadding="false"
    android:gravity="center_horizontal|fill_vertical"
    android:gravity="center_horizontal|fill_vertical"
    android:forceHasOverlappingRendering="false"
    android:background="@drawable/qs_media_background">
    android:background="@drawable/qs_media_background">


    <!-- As per Material Design on Biderectionality, this is forced to LTR in code -->
    <!-- As per Material Design on Biderectionality, this is forced to LTR in code -->
+28 −2
Original line number Original line Diff line number Diff line
@@ -5,6 +5,7 @@ import android.content.Intent
import android.content.res.Configuration
import android.content.res.Configuration
import android.graphics.Color
import android.graphics.Color
import android.provider.Settings.ACTION_MEDIA_CONTROLS_SETTINGS
import android.provider.Settings.ACTION_MEDIA_CONTROLS_SETTINGS
import android.util.MathUtils
import android.view.LayoutInflater
import android.view.LayoutInflater
import android.view.View
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup
@@ -328,9 +329,32 @@ class MediaCarouselController @Inject constructor(
                updatePlayerToState(mediaPlayer, immediately)
                updatePlayerToState(mediaPlayer, immediately)
            }
            }
            maybeResetSettingsCog()
            maybeResetSettingsCog()
            updatePageIndicatorAlpha()
        }
        }
    }
    }


    private fun updatePageIndicatorAlpha() {
        val hostStates = mediaHostStatesManager.mediaHostStates
        val endIsVisible = hostStates[currentEndLocation]?.visible ?: false
        val startIsVisible = hostStates[currentStartLocation]?.visible ?: false
        val startAlpha = if (startIsVisible) 1.0f else 0.0f
        val endAlpha = if (endIsVisible) 1.0f else 0.0f
        var alpha = 1.0f
        if (!endIsVisible || !startIsVisible) {
            var progress = currentTransitionProgress
            if (!endIsVisible) {
                progress = 1.0f - progress
            }
            // Let's fade in quickly at the end where the view is visible
            progress = MathUtils.constrain(
                    MathUtils.map(0.95f, 1.0f, 0.0f, 1.0f, progress),
                    0.0f,
                    1.0f)
            alpha = MathUtils.lerp(startAlpha, endAlpha, progress)
        }
        pageIndicator.alpha = alpha
    }

    private fun updatePageIndicatorLocation() {
    private fun updatePageIndicatorLocation() {
        // Update the location of the page indicator, carousel clipping
        // Update the location of the page indicator, carousel clipping
        val translationX = if (isRtl) {
        val translationX = if (isRtl) {
@@ -352,8 +376,10 @@ class MediaCarouselController @Inject constructor(
        var height = 0
        var height = 0
        for (mediaPlayer in mediaPlayers.values) {
        for (mediaPlayer in mediaPlayers.values) {
            val controller = mediaPlayer.mediaViewController
            val controller = mediaPlayer.mediaViewController
            width = Math.max(width, controller.currentWidth)
            // When transitioning the view to gone, the view gets smaller, but the translation
            height = Math.max(height, controller.currentHeight)
            // Doesn't, let's add the translation
            width = Math.max(width, controller.currentWidth + controller.translationX.toInt())
            height = Math.max(height, controller.currentHeight + controller.translationY.toInt())
        }
        }
        if (width != currentCarouselWidth || height != currentCarouselHeight) {
        if (width != currentCarouselWidth || height != currentCarouselHeight) {
            currentCarouselWidth = width
            currentCarouselWidth = width
+23 −11
Original line number Original line Diff line number Diff line
@@ -329,7 +329,7 @@ class MediaHierarchyManager @Inject constructor(
            applyTargetStateIfNotAnimating()
            applyTargetStateIfNotAnimating()
        } else if (animate) {
        } else if (animate) {
            animator.cancel()
            animator.cancel()
            if (currentAttachmentLocation == IN_OVERLAY ||
            if (currentAttachmentLocation != previousLocation ||
                    !previousHost.hostView.isAttachedToWindow) {
                    !previousHost.hostView.isAttachedToWindow) {
                // Let's animate to the new position, starting from the current position
                // Let's animate to the new position, starting from the current position
                // We also go in here in case the view was detached, since the bounds wouldn't
                // We also go in here in case the view was detached, since the bounds wouldn't
@@ -341,11 +341,13 @@ class MediaHierarchyManager @Inject constructor(
                animationStartBounds.set(previousHost.currentBounds)
                animationStartBounds.set(previousHost.currentBounds)
            }
            }
            adjustAnimatorForTransition(desiredLocation, previousLocation)
            adjustAnimatorForTransition(desiredLocation, previousLocation)
            if (!animationPending) {
                rootView?.let {
                rootView?.let {
                    // Let's delay the animation start until we finished laying out
                    // Let's delay the animation start until we finished laying out
                    animationPending = true
                    animationPending = true
                    it.postOnAnimation(startAnimation)
                    it.postOnAnimation(startAnimation)
                }
                }
            }
        } else {
        } else {
            cancelAnimationAndApplyDesiredState()
            cancelAnimationAndApplyDesiredState()
        }
        }
@@ -403,15 +405,23 @@ class MediaHierarchyManager @Inject constructor(
    }
    }


    /**
    /**
     * Updates the state that the view wants to be in at the end of the animation.
     * Updates the bounds that the view wants to be in at the end of the animation.
     */
     */
    private fun updateTargetState() {
    private fun updateTargetState() {
        if (isCurrentlyInGuidedTransformation()) {
        if (isCurrentlyInGuidedTransformation()) {
            val progress = getTransformationProgress()
            val progress = getTransformationProgress()
            val currentHost = getHost(desiredLocation)!!
            var endHost = getHost(desiredLocation)!!
            val previousHost = getHost(previousLocation)!!
            var starthost = getHost(previousLocation)!!
            val newBounds = currentHost.currentBounds
            // If either of the hosts are invisible, let's keep them at the other host location to
            val previousBounds = previousHost.currentBounds
            // have a nicer disappear animation. Otherwise the currentBounds of the state might
            // be undefined
            if (!endHost.visible) {
                endHost = starthost
            } else if (!starthost.visible) {
                starthost = endHost
            }
            val newBounds = endHost.currentBounds
            val previousBounds = starthost.currentBounds
            targetBounds = interpolateBounds(previousBounds, newBounds, progress)
            targetBounds = interpolateBounds(previousBounds, newBounds, progress)
        } else {
        } else {
            val bounds = getHost(desiredLocation)?.currentBounds ?: return
            val bounds = getHost(desiredLocation)?.currentBounds ?: return
@@ -462,9 +472,11 @@ class MediaHierarchyManager @Inject constructor(
        val previousHost = getHost(previousLocation)
        val previousHost = getHost(previousLocation)
        if (currentHost?.location == LOCATION_QS) {
        if (currentHost?.location == LOCATION_QS) {
            if (previousHost?.location == LOCATION_QQS) {
            if (previousHost?.location == LOCATION_QQS) {
                if (previousHost.visible || statusbarState != StatusBarState.KEYGUARD) {
                    return qsExpansion
                    return qsExpansion
                }
                }
            }
            }
        }
        return -1.0f
        return -1.0f
    }
    }


+30 −29
Original line number Original line Diff line number Diff line
@@ -5,6 +5,7 @@ import android.graphics.Rect
import android.util.ArraySet
import android.util.ArraySet
import android.view.View
import android.view.View
import android.view.View.OnAttachStateChangeListener
import android.view.View.OnAttachStateChangeListener
import com.android.systemui.util.animation.DisappearParameters
import com.android.systemui.util.animation.MeasurementInput
import com.android.systemui.util.animation.MeasurementInput
import com.android.systemui.util.animation.MeasurementOutput
import com.android.systemui.util.animation.MeasurementOutput
import com.android.systemui.util.animation.UniqueObjectHostView
import com.android.systemui.util.animation.UniqueObjectHostView
@@ -128,8 +129,6 @@ class MediaHost @Inject constructor(
    }
    }


    class MediaHostStateHolder @Inject constructor() : MediaHostState {
    class MediaHostStateHolder @Inject constructor() : MediaHostState {
        private var gonePivot: PointF = PointF()

        override var measurementInput: MeasurementInput? = null
        override var measurementInput: MeasurementInput? = null
            set(value) {
            set(value) {
                if (value?.equals(field) != true) {
                if (value?.equals(field) != true) {
@@ -172,16 +171,19 @@ class MediaHost @Inject constructor(
                changedListener?.invoke()
                changedListener?.invoke()
            }
            }


        override fun getPivotX(): Float = gonePivot.x
        override var disappearParameters: DisappearParameters = DisappearParameters()
        override fun getPivotY(): Float = gonePivot.y
            set(value) {
        override fun setGonePivot(x: Float, y: Float) {
                val newHash = value.hashCode()
            if (gonePivot.equals(x, y)) {
                if (lastDisappearHash.equals(newHash)) {
                    return
                    return
                }
                }
            gonePivot.set(x, y)
                field = value
                lastDisappearHash = newHash
                changedListener?.invoke()
                changedListener?.invoke()
            }
            }


        private var lastDisappearHash = disappearParameters.hashCode()

        /**
        /**
         * A listener for all changes. This won't be copied over when invoking [copy]
         * A listener for all changes. This won't be copied over when invoking [copy]
         */
         */
@@ -196,7 +198,7 @@ class MediaHost @Inject constructor(
            mediaHostState.showsOnlyActiveMedia = showsOnlyActiveMedia
            mediaHostState.showsOnlyActiveMedia = showsOnlyActiveMedia
            mediaHostState.measurementInput = measurementInput?.copy()
            mediaHostState.measurementInput = measurementInput?.copy()
            mediaHostState.visible = visible
            mediaHostState.visible = visible
            mediaHostState.gonePivot.set(gonePivot)
            mediaHostState.disappearParameters = disappearParameters.deepCopy()
            mediaHostState.falsingProtectionNeeded = falsingProtectionNeeded
            mediaHostState.falsingProtectionNeeded = falsingProtectionNeeded
            return mediaHostState
            return mediaHostState
        }
        }
@@ -220,7 +222,7 @@ class MediaHost @Inject constructor(
            if (falsingProtectionNeeded != other.falsingProtectionNeeded) {
            if (falsingProtectionNeeded != other.falsingProtectionNeeded) {
                return false
                return false
            }
            }
            if (!gonePivot.equals(other.getPivotX(), other.getPivotY())) {
            if (!disappearParameters.equals(other.disappearParameters)) {
                return false
                return false
            }
            }
            return true
            return true
@@ -232,12 +234,23 @@ class MediaHost @Inject constructor(
            result = 31 * result + falsingProtectionNeeded.hashCode()
            result = 31 * result + falsingProtectionNeeded.hashCode()
            result = 31 * result + showsOnlyActiveMedia.hashCode()
            result = 31 * result + showsOnlyActiveMedia.hashCode()
            result = 31 * result + if (visible) 1 else 2
            result = 31 * result + if (visible) 1 else 2
            result = 31 * result + gonePivot.hashCode()
            result = 31 * result + disappearParameters.hashCode()
            return result
            return result
        }
        }
    }
    }
}
}


/**
 * A description of a media host state that describes the behavior whenever the media carousel
 * is hosted. The HostState notifies the media players of changes to their properties, who
 * in turn will create view states from it.
 * When adding a new property to this, make sure to update the listener and notify them
 * about the changes.
 * In case you need to have a different rendering based on the state, you can add a new
 * constraintState to the [MediaViewController]. Otherwise, similar host states will resolve
 * to the same viewstate, a behavior that is described in [CacheKey]. Make sure to only update
 * that key if the underlying view needs to have a different measurement.
 */
interface MediaHostState {
interface MediaHostState {


    /**
    /**
@@ -268,23 +281,11 @@ interface MediaHostState {
    var falsingProtectionNeeded: Boolean
    var falsingProtectionNeeded: Boolean


    /**
    /**
     * Sets the pivot point when clipping the height or width.
     * The parameters how the view disappears from this location when going to a host that's not
     * Clipping happens when animating visibility when we're visible in QS but not on QQS,
     * visible. If modified, make sure to set this value again on the host to ensure the values
     * for example.
     * are propagated
     */
    fun setGonePivot(x: Float, y: Float)

    /**
     * x position of pivot, from 0 to 1
     * @see [setGonePivot]
     */
    fun getPivotX(): Float

    /**
     * y position of pivot, from 0 to 1
     * @see [setGonePivot]
     */
     */
    fun getPivotY(): Float
    var disappearParameters: DisappearParameters


    /**
    /**
     * Get a copy of this view state, deepcopying all appropriate members
     * Get a copy of this view state, deepcopying all appropriate members
Loading