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

Commit c9e3c707 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Fix clipping during media squishing and general behavior" into tm-qpr-dev

parents 56fbcccf fab74782
Loading
Loading
Loading
Loading
+53 −12
Original line number Original line Diff line number Diff line
@@ -82,6 +82,13 @@ constructor(
                R.id.header_artist,
                R.id.header_artist,
                R.id.actionPlayPause,
                R.id.actionPlayPause,
            )
            )

        val backgroundIds =
            setOf(
                R.id.album_art,
                R.id.turbulence_noise_view,
                R.id.touch_ripple_view,
            )
    }
    }


    /** A listener when the current dimensions of the player change */
    /** A listener when the current dimensions of the player change */
@@ -295,7 +302,8 @@ constructor(
        squishFraction: Float
        squishFraction: Float
    ): TransitionViewState {
    ): TransitionViewState {
        val squishedViewState = viewState.copy()
        val squishedViewState = viewState.copy()
        squishedViewState.height = (squishedViewState.height * squishFraction).toInt()
        val squishedHeight = (squishedViewState.measureHeight * squishFraction).toInt()
        squishedViewState.height = squishedHeight
        controlIds.forEach { id ->
        controlIds.forEach { id ->
            squishedViewState.widgetStates.get(id)?.let { state ->
            squishedViewState.widgetStates.get(id)?.let { state ->
                state.alpha = calculateAlpha(squishFraction, CONTROLS_DELAY, DURATION)
                state.alpha = calculateAlpha(squishFraction, CONTROLS_DELAY, DURATION)
@@ -308,6 +316,14 @@ constructor(
            }
            }
        }
        }


        // We are not overriding the squishedViewStates height but only the children to avoid
        // them remeasuring the whole view. Instead it just remains as the original size
        backgroundIds.forEach { id ->
            squishedViewState.widgetStates.get(id)?.let { state ->
                state.height = squishedHeight
            }
        }

        RecommendationViewHolder.mediaContainersIds.forEach { id ->
        RecommendationViewHolder.mediaContainersIds.forEach { id ->
            squishedViewState.widgetStates.get(id)?.let { state ->
            squishedViewState.widgetStates.get(id)?.let { state ->
                state.alpha = calculateAlpha(squishFraction, MEDIACONTAINERS_DELAY, DURATION)
                state.alpha = calculateAlpha(squishFraction, MEDIACONTAINERS_DELAY, DURATION)
@@ -421,10 +437,9 @@ constructor(
    fun getMeasurementsForState(hostState: MediaHostState): MeasurementOutput? =
    fun getMeasurementsForState(hostState: MediaHostState): MeasurementOutput? =
        traceSection("MediaViewController#getMeasurementsForState") {
        traceSection("MediaViewController#getMeasurementsForState") {
            // measurements should never factor in the squish fraction
            // measurements should never factor in the squish fraction
            val viewState =
            val viewState = obtainViewState(hostState) ?: return null
                obtainViewState(hostState.copy().also { it.squishFraction = 1.0f }) ?: return null
            measurement.measuredWidth = viewState.measureWidth
            measurement.measuredWidth = viewState.width
            measurement.measuredHeight = viewState.measureHeight
            measurement.measuredHeight = viewState.height
            return measurement
            return measurement
        }
        }


@@ -453,7 +468,7 @@ constructor(
            // The view might not be bound yet or has never been measured and in that case will be
            // The view might not be bound yet or has never been measured and in that case will be
            // reset once the state is fully available
            // reset once the state is fully available
            var endViewState = obtainViewState(endHostState) ?: return
            var endViewState = obtainViewState(endHostState) ?: return
            endViewState = updateViewStateToCarouselSize(endViewState, endLocation, tmpState2)!!
            endViewState = updateViewStateSize(endViewState, endLocation, tmpState2)!!
            layoutController.setMeasureState(endViewState)
            layoutController.setMeasureState(endViewState)


            // If the view isn't bound, we can drop the animation, otherwise we'll execute it
            // If the view isn't bound, we can drop the animation, otherwise we'll execute it
@@ -464,7 +479,7 @@ constructor(


            val result: TransitionViewState
            val result: TransitionViewState
            var startViewState = obtainViewState(startHostState)
            var startViewState = obtainViewState(startHostState)
            startViewState = updateViewStateToCarouselSize(startViewState, startLocation, tmpState3)
            startViewState = updateViewStateSize(startViewState, startLocation, tmpState3)


            if (!endHostState.visible) {
            if (!endHostState.visible) {
                // Let's handle the case where the end is gone first. In this case we take the
                // Let's handle the case where the end is gone first. In this case we take the
@@ -517,18 +532,38 @@ constructor(
            )
            )
        }
        }


    private fun updateViewStateToCarouselSize(
    private fun updateViewStateSize(
        viewState: TransitionViewState?,
        viewState: TransitionViewState?,
        location: Int,
        location: Int,
        outState: TransitionViewState
        outState: TransitionViewState
    ): TransitionViewState? {
    ): TransitionViewState? {
        val result = viewState?.copy(outState) ?: return null
        var result = viewState?.copy(outState) ?: return null
        val state = mediaHostStatesManager.mediaHostStates[location]
        val overrideSize = mediaHostStatesManager.carouselSizes[location]
        val overrideSize = mediaHostStatesManager.carouselSizes[location]
        var overridden = false
        overrideSize?.let {
        overrideSize?.let {
            // To be safe we're using a maximum here. The override size should always be set
            // To be safe we're using a maximum here. The override size should always be set
            // properly though.
            // properly though.
            result.height = Math.max(it.measuredHeight, result.height)
            if (result.measureHeight != it.measuredHeight
            result.width = Math.max(it.measuredWidth, result.width)
                    || result.measureWidth != it.measuredWidth) {
                result.measureHeight = Math.max(it.measuredHeight, result.measureHeight)
                result.measureWidth = Math.max(it.measuredWidth, result.measureWidth)
                // The measureHeight and the shown height should both be set to the overridden height
                result.height = result.measureHeight
                result.width = result.measureWidth
                // Make sure all background views are also resized such that their size is correct
                backgroundIds.forEach { id ->
                    result.widgetStates.get(id)?.let { state ->
                        state.height = result.height
                        state.width = result.width
                    }
                }
                overridden = true
            }
        }
        if (overridden && state != null && state.squishFraction <= 1f) {
            // Let's squish the media player if our size was overridden
            result = squishViewState(result, state.squishFraction)
        }
        }
        logger.logMediaSize("update to carousel", result.width, result.height)
        logger.logMediaSize("update to carousel", result.width, result.height)
        return result
        return result
@@ -562,7 +597,13 @@ constructor(
     */
     */
    private fun obtainViewStateForLocation(@MediaLocation location: Int): TransitionViewState? {
    private fun obtainViewStateForLocation(@MediaLocation location: Int): TransitionViewState? {
        val mediaHostState = mediaHostStatesManager.mediaHostStates[location] ?: return null
        val mediaHostState = mediaHostStatesManager.mediaHostStates[location] ?: return null
        return obtainViewState(mediaHostState)
        val viewState = obtainViewState(mediaHostState)
        if (viewState != null) {
            // update the size of the viewstate for the location with the override
            updateViewStateSize(viewState, location, tmpState)
            return tmpState
        }
        return viewState
    }
    }


    /**
    /**
+26 −2
Original line number Original line Diff line number Diff line
@@ -59,8 +59,8 @@ class TransitionLayout @JvmOverloads constructor(
     */
     */
    var measureState: TransitionViewState = TransitionViewState()
    var measureState: TransitionViewState = TransitionViewState()
        set(value) {
        set(value) {
            val newWidth = value.width
            val newWidth = value.measureWidth
            val newHeight = value.height
            val newHeight = value.measureHeight
            if (newWidth != desiredMeasureWidth || newHeight != desiredMeasureHeight) {
            if (newWidth != desiredMeasureWidth || newHeight != desiredMeasureHeight) {
                desiredMeasureWidth = newWidth
                desiredMeasureWidth = newWidth
                desiredMeasureHeight = newHeight
                desiredMeasureHeight = newHeight
@@ -318,8 +318,28 @@ class TransitionLayout @JvmOverloads constructor(


class TransitionViewState {
class TransitionViewState {
    var widgetStates: MutableMap<Int, WidgetState> = mutableMapOf()
    var widgetStates: MutableMap<Int, WidgetState> = mutableMapOf()

    /**
     * The visible width of this ViewState. This may differ from the measuredWidth when e.g.
     * squishing the view
     */
    var width: Int = 0
    var width: Int = 0

    /**
     * The visible height of this ViewState. This may differ from the measuredHeight when e.g.
     * squishing the view
     */
    var height: Int = 0
    var height: Int = 0

    /**
     * The height that determines the measured dimensions of the view
     */
    var measureHeight: Int = 0

    /**
     * The width that determines the measured dimensions of the view
     */
    var measureWidth: Int = 0
    var alpha: Float = 1.0f
    var alpha: Float = 1.0f
    val translation = PointF()
    val translation = PointF()
    val contentTranslation = PointF()
    val contentTranslation = PointF()
@@ -328,6 +348,8 @@ class TransitionViewState {
        val copy = reusedState ?: TransitionViewState()
        val copy = reusedState ?: TransitionViewState()
        copy.width = width
        copy.width = width
        copy.height = height
        copy.height = height
        copy.measureHeight = measureHeight
        copy.measureWidth = measureWidth
        copy.alpha = alpha
        copy.alpha = alpha
        copy.translation.set(translation.x, translation.y)
        copy.translation.set(translation.x, translation.y)
        copy.contentTranslation.set(contentTranslation.x, contentTranslation.y)
        copy.contentTranslation.set(contentTranslation.x, contentTranslation.y)
@@ -348,6 +370,8 @@ class TransitionViewState {
        }
        }
        width = transitionLayout.measuredWidth
        width = transitionLayout.measuredWidth
        height = transitionLayout.measuredHeight
        height = transitionLayout.measuredHeight
        measureWidth = width
        measureHeight = height
        translation.set(0.0f, 0.0f)
        translation.set(0.0f, 0.0f)
        contentTranslation.set(0.0f, 0.0f)
        contentTranslation.set(0.0f, 0.0f)
        alpha = 1.0f
        alpha = 1.0f
+9 −0
Original line number Original line Diff line number Diff line
@@ -234,6 +234,15 @@ open class TransitionLayoutController {
                    progress).toInt()
                    progress).toInt()
            height = MathUtils.lerp(startState.height.toFloat(), endState.height.toFloat(),
            height = MathUtils.lerp(startState.height.toFloat(), endState.height.toFloat(),
                    progress).toInt()
                    progress).toInt()
            // If we're at the start, let's measure with the starting dimensions, otherwise always
            // with the end state
            if (progress == 0.0f) {
                measureWidth = startState.measureWidth
                measureHeight = startState.measureHeight
            } else {
                measureWidth = endState.measureWidth
                measureHeight = endState.measureHeight
            }
            translation.x = MathUtils.lerp(startState.translation.x, endState.translation.x,
            translation.x = MathUtils.lerp(startState.translation.x, endState.translation.x,
                    progress)
                    progress)
            translation.y = MathUtils.lerp(startState.translation.y, endState.translation.y,
            translation.y = MathUtils.lerp(startState.translation.y, endState.translation.y,
+9 −1
Original line number Original line Diff line number Diff line
@@ -58,6 +58,7 @@ class MediaViewControllerTest : SysuiTestCase() {
    @Mock private lateinit var mockCopiedState: TransitionViewState
    @Mock private lateinit var mockCopiedState: TransitionViewState
    @Mock private lateinit var detailWidgetState: WidgetState
    @Mock private lateinit var detailWidgetState: WidgetState
    @Mock private lateinit var controlWidgetState: WidgetState
    @Mock private lateinit var controlWidgetState: WidgetState
    @Mock private lateinit var bgWidgetState: WidgetState
    @Mock private lateinit var mediaTitleWidgetState: WidgetState
    @Mock private lateinit var mediaTitleWidgetState: WidgetState
    @Mock private lateinit var mediaContainerWidgetState: WidgetState
    @Mock private lateinit var mediaContainerWidgetState: WidgetState


@@ -75,7 +76,10 @@ class MediaViewControllerTest : SysuiTestCase() {
    @Test
    @Test
    fun testObtainViewState_applySquishFraction_toPlayerTransitionViewState_height() {
    fun testObtainViewState_applySquishFraction_toPlayerTransitionViewState_height() {
        mediaViewController.attach(player, MediaViewController.TYPE.PLAYER)
        mediaViewController.attach(player, MediaViewController.TYPE.PLAYER)
        player.measureState = TransitionViewState().apply { this.height = 100 }
        player.measureState = TransitionViewState().apply {
            this.height = 100
            this.measureHeight = 100
        }
        mediaHostStateHolder.expansion = 1f
        mediaHostStateHolder.expansion = 1f
        val widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY)
        val widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY)
        val heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY)
        val heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY)
@@ -85,10 +89,12 @@ class MediaViewControllerTest : SysuiTestCase() {
        // Test no squish
        // Test no squish
        mediaHostStateHolder.squishFraction = 1f
        mediaHostStateHolder.squishFraction = 1f
        assertTrue(mediaViewController.obtainViewState(mediaHostStateHolder)!!.height == 100)
        assertTrue(mediaViewController.obtainViewState(mediaHostStateHolder)!!.height == 100)
        assertTrue(mediaViewController.obtainViewState(mediaHostStateHolder)!!.measureHeight == 100)


        // Test half squish
        // Test half squish
        mediaHostStateHolder.squishFraction = 0.5f
        mediaHostStateHolder.squishFraction = 0.5f
        assertTrue(mediaViewController.obtainViewState(mediaHostStateHolder)!!.height == 50)
        assertTrue(mediaViewController.obtainViewState(mediaHostStateHolder)!!.height == 50)
        assertTrue(mediaViewController.obtainViewState(mediaHostStateHolder)!!.measureHeight == 100)
    }
    }


    @Test
    @Test
@@ -104,10 +110,12 @@ class MediaViewControllerTest : SysuiTestCase() {
        // Test no squish
        // Test no squish
        mediaHostStateHolder.squishFraction = 1f
        mediaHostStateHolder.squishFraction = 1f
        assertTrue(mediaViewController.obtainViewState(mediaHostStateHolder)!!.height == 100)
        assertTrue(mediaViewController.obtainViewState(mediaHostStateHolder)!!.height == 100)
        assertTrue(mediaViewController.obtainViewState(mediaHostStateHolder)!!.measureHeight == 100)


        // Test half squish
        // Test half squish
        mediaHostStateHolder.squishFraction = 0.5f
        mediaHostStateHolder.squishFraction = 0.5f
        assertTrue(mediaViewController.obtainViewState(mediaHostStateHolder)!!.height == 50)
        assertTrue(mediaViewController.obtainViewState(mediaHostStateHolder)!!.height == 50)
        assertTrue(mediaViewController.obtainViewState(mediaHostStateHolder)!!.measureHeight == 100)
    }
    }


    @Test
    @Test