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

Commit f409d7f5 authored by Selim Cinek's avatar Selim Cinek
Browse files

Ensured that all players have the same size

Previously, Media players could have different sizes
if for example their album art was gone. We now enforce
that all of them have the same size, determined by
the max of their wrap_content heights.

Fixes: 159864229
Test: add a player without album art, e.g. a resumable player. Observe consistent measurements with others
Change-Id: Iaacb2b78b7d92ed21e382d69b3bf599dbd7b1a6e
parent d43e376c
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -299,6 +299,7 @@ class MediaCarouselController @Inject constructor(
        if (numPages == 1) {
            pageIndicator.setLocation(0f)
        }
        updatePageIndicatorAlpha()
    }

    /**
+1 −2
Original line number Diff line number Diff line
package com.android.systemui.media

import android.graphics.PointF
import android.graphics.Rect
import android.util.ArraySet
import android.view.View
@@ -101,7 +100,7 @@ class MediaHost @Inject constructor(
                }
                // This will trigger a state change that ensures that we now have a state available
                state.measurementInput = input
                return mediaHostStatesManager.getPlayerDimensions(state)
                return mediaHostStatesManager.updateCarouselDimensions(location, state)
            }
        }

+12 −1
Original line number Diff line number Diff line
@@ -31,6 +31,12 @@ class MediaHostStatesManager @Inject constructor() {
    private val callbacks: MutableSet<Callback> = mutableSetOf()
    private val controllers: MutableSet<MediaViewController> = mutableSetOf()

    /**
     * The overall sizes of the carousel. This is needed to make sure all players in the carousel
     * have equal size.
     */
    val carouselSizes: MutableMap<Int, MeasurementOutput> = mutableMapOf()

    /**
     * A map with all media states of all locations.
     */
@@ -45,6 +51,7 @@ class MediaHostStatesManager @Inject constructor() {
        if (!hostState.equals(currentState)) {
            val newState = hostState.copy()
            mediaHostStates.put(location, newState)
            updateCarouselDimensions(location, hostState)
            // First update all the controllers to ensure they get the chance to measure
            for (controller in controllers) {
                controller.stateCallback.onHostStateChanged(location, newState)
@@ -61,7 +68,10 @@ class MediaHostStatesManager @Inject constructor() {
     * Get the dimensions of all players combined, which determines the overall height of the
     * media carousel and the media hosts.
     */
    fun getPlayerDimensions(hostState: MediaHostState): MeasurementOutput {
    fun updateCarouselDimensions(
        @MediaLocation location: Int,
        hostState: MediaHostState
    ): MeasurementOutput {
        val result = MeasurementOutput(0, 0)
        for (controller in controllers) {
            val measurement = controller.getMeasurementsForState(hostState)
@@ -74,6 +84,7 @@ class MediaHostStatesManager @Inject constructor() {
                }
            }
        }
        carouselSizes[location] = result
        return result
    }

+30 −3
Original line number Diff line number Diff line
@@ -78,6 +78,16 @@ class MediaViewController @Inject constructor(
     */
    private val tmpState = TransitionViewState()

    /**
     * A temporary state used to store intermediate measurements.
     */
    private val tmpState2 = TransitionViewState()

    /**
     * A temporary state used to store intermediate measurements.
     */
    private val tmpState3 = TransitionViewState()

    /**
     * A temporary cache key to be used to look up cache entries
     */
@@ -304,8 +314,8 @@ class MediaViewController @Inject constructor(
        // Obtain the view state that we'd want to be at the end
        // 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
        val endViewState = obtainViewState(endHostState) ?: return

        var endViewState = obtainViewState(endHostState) ?: return
        endViewState = updateViewStateToCarouselSize(endViewState, endLocation, tmpState2)!!
        layoutController.setMeasureState(endViewState)

        // If the view isn't bound, we can drop the animation, otherwise we'll execute it
@@ -315,7 +325,8 @@ class MediaViewController @Inject constructor(
        }

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

        if (!endHostState.visible) {
            // Let's handle the case where the end is gone first. In this case we take the
@@ -350,6 +361,22 @@ class MediaViewController @Inject constructor(
                animationDelay)
    }

    private fun updateViewStateToCarouselSize(
        viewState: TransitionViewState?,
        location: Int,
        outState: TransitionViewState
    ) : TransitionViewState? {
        val result = viewState?.copy(outState) ?: return null
        val overrideSize = mediaHostStatesManager.carouselSizes[location]
        overrideSize?.let {
            // To be safe we're using a maximum here. The override size should always be set
            // properly though.
            result.height = Math.max(it.measuredHeight, result.height)
            result.width = Math.max(it.measuredWidth, result.width)
        }
        return result
    }

    /**
     * Retrieves the [TransitionViewState] and [MediaHostState] of a [@MediaLocation].
     * In the event of [location] not being visible, [locationWhenHidden] will be used instead.