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

Commit 1a305a0f authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Towards paged layout: introduce view holder" into rvc-dev am: 93c07bb2

Change-Id: I9e1d7fd753cc762b04cdf8195c647d0c6c5f159d
parents 574fbd14 93c07bb2
Loading
Loading
Loading
Loading
+99 −84
Original line number Diff line number Diff line
@@ -37,9 +37,7 @@ import android.media.session.MediaSession;
import android.media.session.PlaybackState;
import android.service.media.MediaBrowserService;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
@@ -90,16 +88,14 @@ public class MediaControlPanel {
    };

    private final SeekBarViewModel mSeekBarViewModel;
    private final SeekBarObserver mSeekBarObserver;
    private SeekBarObserver mSeekBarObserver;
    private final Executor mForegroundExecutor;
    protected final Executor mBackgroundExecutor;
    private final ActivityStarter mActivityStarter;
    private final LayoutAnimationHelper mLayoutAnimationHelper;
    private LayoutAnimationHelper mLayoutAnimationHelper;

    private Context mContext;
    private MotionLayout mMediaNotifView;
    private final View mBackground;
    private View mSeamless;
    private PlayerViewHolder mViewHolder;
    private MediaSession.Token mToken;
    private MediaController mController;
    private int mForegroundColor;
@@ -107,7 +103,7 @@ public class MediaControlPanel {
    private MediaDevice mDevice;
    protected ComponentName mServiceComponent;
    private boolean mIsRegistered = false;
    private final List<KeyFrames> mKeyFrames;
    private List<KeyFrames> mKeyFrames;
    private String mKey;
    private int mAlbumArtSize;
    private int mAlbumArtRadius;
@@ -166,37 +162,27 @@ public class MediaControlPanel {
    /**
     * Initialize a new control panel
     * @param context
     * @param parent
     * @param routeManager Manager used to listen for device change events.
     * @param foregroundExecutor foreground executor
     * @param backgroundExecutor background executor, used for processing artwork
     * @param activityStarter activity starter
     */
    public MediaControlPanel(Context context, ViewGroup parent,
            @Nullable LocalMediaManager routeManager, Executor foregroundExecutor,
            DelayableExecutor backgroundExecutor, ActivityStarter activityStarter) {
    public MediaControlPanel(Context context, @Nullable LocalMediaManager routeManager,
            Executor foregroundExecutor, DelayableExecutor backgroundExecutor,
            ActivityStarter activityStarter) {
        mContext = context;
        LayoutInflater inflater = LayoutInflater.from(mContext);
        mMediaNotifView = (MotionLayout) inflater.inflate(R.layout.qs_media_panel, parent, false);
        mBackground = mMediaNotifView.findViewById(R.id.media_background);
        mLayoutAnimationHelper = new LayoutAnimationHelper(mMediaNotifView);
        GoneChildrenHideHelper.clipGoneChildrenOnLayout(mMediaNotifView);
        mKeyFrames = mMediaNotifView.getDefinedTransitions().get(0).getKeyFrameList();
        mLocalMediaManager = routeManager;
        mForegroundExecutor = foregroundExecutor;
        mBackgroundExecutor = backgroundExecutor;
        mActivityStarter = activityStarter;
        mSeekBarViewModel = new SeekBarViewModel(backgroundExecutor);
        mSeekBarObserver = new SeekBarObserver(getView());
        mSeekBarViewModel.getProgress().observeForever(mSeekBarObserver);
        SeekBar bar = getView().findViewById(R.id.media_progress_bar);
        bar.setOnSeekBarChangeListener(mSeekBarViewModel.getSeekBarListener());
        bar.setOnTouchListener(mSeekBarViewModel.getSeekBarTouchListener());
        loadDimens();
    }

    public void onDestroy() {
        if (mSeekBarObserver != null) {
            mSeekBarViewModel.getProgress().removeObserver(mSeekBarObserver);
        }
        makeInactive();
    }

@@ -207,11 +193,12 @@ public class MediaControlPanel {
    }

    /**
     * Get the view used to display media controls
     * @return the view
     * Get the view holder used to display media controls
     * @return the view holder
     */
    public MotionLayout getView() {
        return mMediaNotifView;
    @Nullable
    public PlayerViewHolder getView() {
        return mViewHolder;
    }

    /**
@@ -234,10 +221,27 @@ public class MediaControlPanel {
        return mContext;
    }

    /** Attaches the player to the view holder. */
    public void attach(PlayerViewHolder vh) {
        mViewHolder = vh;
        MotionLayout motionView = vh.getPlayer();
        mLayoutAnimationHelper = new LayoutAnimationHelper(motionView);
        GoneChildrenHideHelper.clipGoneChildrenOnLayout(motionView);
        mKeyFrames = motionView.getDefinedTransitions().get(0).getKeyFrameList();
        mSeekBarObserver = new SeekBarObserver(motionView);
        mSeekBarViewModel.getProgress().observeForever(mSeekBarObserver);
        SeekBar bar = vh.getSeekBar();
        bar.setOnSeekBarChangeListener(mSeekBarViewModel.getSeekBarListener());
        bar.setOnTouchListener(mSeekBarViewModel.getSeekBarTouchListener());
    }

    /**
     * Bind this view based on the data given
     */
    public void bind(@NotNull MediaData data) {
        if (mViewHolder == null) {
            return;
        }
        MediaSession.Token token = data.getToken();
        mForegroundColor = data.getForegroundColor();
        mBackgroundColor = data.getBackgroundColor();
@@ -254,8 +258,8 @@ public class MediaControlPanel {

        mController = new MediaController(mContext, mToken);

        ConstraintSet expandedSet = mMediaNotifView.getConstraintSet(R.id.expanded);
        ConstraintSet collapsedSet = mMediaNotifView.getConstraintSet(R.id.collapsed);
        ConstraintSet expandedSet = mViewHolder.getPlayer().getConstraintSet(R.id.expanded);
        ConstraintSet collapsedSet = mViewHolder.getPlayer().getConstraintSet(R.id.collapsed);

        // Try to find a browser service component for this app
        // TODO also check for a media button receiver intended for restarting (b/154127084)
@@ -281,53 +285,51 @@ public class MediaControlPanel {

        mController.registerCallback(mSessionCallback);

        mMediaNotifView.requireViewById(R.id.media_background).setBackgroundTintList(
        mViewHolder.getBackground().setBackgroundTintList(
                ColorStateList.valueOf(mBackgroundColor));

        // Click action
        PendingIntent clickIntent = data.getClickIntent();
        if (clickIntent != null) {
            mMediaNotifView.setOnClickListener(v -> {
            mViewHolder.getPlayer().setOnClickListener(v -> {
                mActivityStarter.postStartActivityDismissingKeyguard(clickIntent);
            });
        }

        ImageView albumView = mMediaNotifView.findViewById(R.id.album_art);
        ImageView albumView = mViewHolder.getAlbumView();
        // TODO: migrate this to a view with rounded corners instead of baking the rounding
        // into the bitmap
        Drawable artwork = createRoundedBitmap(data.getArtwork());
        albumView.setImageDrawable(artwork);

        // App icon
        ImageView appIcon = mMediaNotifView.requireViewById(R.id.icon);
        ImageView appIcon = mViewHolder.getAppIcon();
        Drawable iconDrawable = data.getAppIcon().mutate();
        iconDrawable.setTint(mForegroundColor);
        appIcon.setImageDrawable(iconDrawable);

        // Song name
        TextView titleText = mMediaNotifView.requireViewById(R.id.header_title);
        TextView titleText = mViewHolder.getTitleText();
        titleText.setText(data.getSong());
        titleText.setTextColor(data.getForegroundColor());

        // App title
        TextView appName = mMediaNotifView.requireViewById(R.id.app_name);
        TextView appName = mViewHolder.getAppName();
        appName.setText(data.getApp());
        appName.setTextColor(mForegroundColor);

        // Artist name
        TextView artistText = mMediaNotifView.requireViewById(R.id.header_artist);
        TextView artistText = mViewHolder.getArtistText();
        artistText.setText(data.getArtist());
        artistText.setTextColor(mForegroundColor);

        // Transfer chip
        mSeamless = mMediaNotifView.findViewById(R.id.media_seamless);
        if (mSeamless != null) {
        if (mLocalMediaManager != null) {
                mSeamless.setVisibility(View.VISIBLE);
            mViewHolder.getSeamless().setVisibility(View.VISIBLE);
            setVisibleAndAlpha(collapsedSet, R.id.media_seamless, true /*visible */);
            setVisibleAndAlpha(expandedSet, R.id.media_seamless, true /*visible */);
            updateDevice(mLocalMediaManager.getCurrentConnectedDevice());
                mSeamless.setOnClickListener(v -> {
            mViewHolder.getSeamless().setOnClickListener(v -> {
                final Intent intent = new Intent()
                        .setAction(MediaOutputSliceConstants.ACTION_MEDIA_OUTPUT)
                        .putExtra(MediaOutputSliceConstants.EXTRA_PACKAGE_NAME,
@@ -339,7 +341,6 @@ public class MediaControlPanel {
        } else {
            Log.d(TAG, "LocalMediaManager is null. Not binding output chip for pkg=" + pkgName);
        }
        }
        PlaybackInfo playbackInfo = mController.getPlaybackInfo();
        if (playbackInfo != null) {
            mIsRemotePlayback = playbackInfo.getPlaybackType() == PlaybackInfo.PLAYBACK_TYPE_REMOTE;
@@ -353,16 +354,16 @@ public class MediaControlPanel {
        List<MediaAction> actionIcons = data.getActions();
        for (; i < actionIcons.size() && i < ACTION_IDS.length; i++) {
            int actionId = ACTION_IDS[i];
            final ImageButton button = mMediaNotifView.findViewById(actionId);
            final ImageButton button = mViewHolder.getAction(actionId);
            MediaAction mediaAction = actionIcons.get(i);
            button.setImageDrawable(mediaAction.getDrawable());
            button.setContentDescription(mediaAction.getContentDescription());
            button.setImageTintList(ColorStateList.valueOf(mForegroundColor));
            PendingIntent actionIntent = mediaAction.getIntent();

            if (mBackground.getBackground() instanceof IlluminationDrawable) {
                ((IlluminationDrawable) mBackground.getBackground())
                        .setupTouch(button, mMediaNotifView);
            if (mViewHolder.getBackground().getBackground() instanceof IlluminationDrawable) {
                ((IlluminationDrawable) mViewHolder.getBackground().getBackground())
                        .setupTouch(button, mViewHolder.getPlayer());
            }

            button.setOnClickListener(v -> {
@@ -397,8 +398,8 @@ public class MediaControlPanel {
        makeActive();

        // Update both constraint sets to regenerate the animation.
        mMediaNotifView.updateState(R.id.collapsed, collapsedSet);
        mMediaNotifView.updateState(R.id.expanded, expandedSet);
        mViewHolder.getPlayer().updateState(R.id.collapsed, collapsedSet);
        mViewHolder.getPlayer().updateState(R.id.expanded, expandedSet);
    }

    @UiThread
@@ -441,6 +442,9 @@ public class MediaControlPanel {
     * @param visible is the view visible
     */
    private void updateKeyFrameVisibility(int actionId, boolean visible) {
        if (mKeyFrames == null) {
            return;
        }
        for (int i = 0; i < mKeyFrames.size(); i++) {
            KeyFrames keyframe = mKeyFrames.get(i);
            ArrayList<Key> viewKeyFrames = keyframe.getKeyFramesForView(actionId);
@@ -528,38 +532,38 @@ public class MediaControlPanel {
     * @param device device information to display
     */
    private void updateDevice(MediaDevice device) {
        if (mSeamless == null) {
            return;
        }
        mForegroundExecutor.execute(() -> {
            updateChipInternal(device);
        });
    }

    private void updateChipInternal(MediaDevice device) {
        if (mViewHolder == null) {
            return;
        }
        ColorStateList fgTintList = ColorStateList.valueOf(mForegroundColor);

        // Update the outline color
        LinearLayout viewLayout = (LinearLayout) mSeamless;
        LinearLayout viewLayout = (LinearLayout) mViewHolder.getSeamless();
        RippleDrawable bkgDrawable = (RippleDrawable) viewLayout.getBackground();
        GradientDrawable rect = (GradientDrawable) bkgDrawable.getDrawable(0);
        rect.setStroke(2, mForegroundColor);
        rect.setColor(mBackgroundColor);

        ImageView iconView = mSeamless.findViewById(R.id.media_seamless_image);
        TextView deviceName = mSeamless.findViewById(R.id.media_seamless_text);
        ImageView iconView = mViewHolder.getSeamlessIcon();
        TextView deviceName = mViewHolder.getSeamlessText();
        deviceName.setTextColor(fgTintList);

        if (mIsRemotePlayback) {
            mSeamless.setEnabled(false);
            mSeamless.setAlpha(0.38f);
            mViewHolder.getSeamless().setEnabled(false);
            mViewHolder.getSeamless().setAlpha(0.38f);
            iconView.setImageResource(R.drawable.ic_hardware_speaker);
            iconView.setVisibility(View.VISIBLE);
            iconView.setImageTintList(fgTintList);
            deviceName.setText(R.string.media_seamless_remote_device);
        } else if (device != null) {
            mSeamless.setEnabled(true);
            mSeamless.setAlpha(1f);
            mViewHolder.getSeamless().setEnabled(true);
            mViewHolder.getSeamless().setAlpha(1f);
            Drawable icon = device.getIcon();
            iconView.setVisibility(View.VISIBLE);
            iconView.setImageTintList(fgTintList);
@@ -575,8 +579,8 @@ public class MediaControlPanel {
        } else {
            // Reset to default
            Log.d(TAG, "device is null. Not binding output chip.");
            mSeamless.setEnabled(true);
            mSeamless.setAlpha(1f);
            mViewHolder.getSeamless().setEnabled(true);
            mViewHolder.getSeamless().setAlpha(1f);
            iconView.setVisibility(View.GONE);
            deviceName.setText(com.android.internal.R.string.ext_media_seamless_action);
        }
@@ -601,17 +605,20 @@ public class MediaControlPanel {
     * Hide the media buttons and show only a restart button
     */
    protected void resetButtons() {
        if (mViewHolder == null) {
            return;
        }
        // Hide all the old buttons

        ConstraintSet expandedSet = mMediaNotifView.getConstraintSet(R.id.expanded);
        ConstraintSet collapsedSet = mMediaNotifView.getConstraintSet(R.id.collapsed);
        ConstraintSet expandedSet = mViewHolder.getPlayer().getConstraintSet(R.id.expanded);
        ConstraintSet collapsedSet = mViewHolder.getPlayer().getConstraintSet(R.id.collapsed);
        for (int i = 1; i < ACTION_IDS.length; i++) {
            setVisibleAndAlpha(expandedSet, ACTION_IDS[i], false /*visible */);
            setVisibleAndAlpha(collapsedSet, ACTION_IDS[i], false /*visible */);
        }

        // Add a restart button
        ImageButton btn = mMediaNotifView.findViewById(ACTION_IDS[0]);
        ImageButton btn = mViewHolder.getAction0();
        btn.setOnClickListener(v -> {
            Log.d(TAG, "Attempting to restart session");
            if (mQSMediaBrowser != null) {
@@ -639,9 +646,9 @@ public class MediaControlPanel {
        mSeekBarViewModel.clearController();
        // TODO: fix guts
        //        View guts = mMediaNotifView.findViewById(R.id.media_guts);
        View options = mMediaNotifView.findViewById(R.id.qs_media_controls_options);
        View options = mViewHolder.getOptions();

        mMediaNotifView.setOnLongClickListener(v -> {
        mViewHolder.getPlayer().setOnLongClickListener(v -> {
            // Replace player view with close/cancel view
//            guts.setVisibility(View.GONE);
            options.setVisibility(View.VISIBLE);
@@ -748,20 +755,28 @@ public class MediaControlPanel {
    protected void removePlayer() { }

    public void measure(@Nullable MediaMeasurementInput input) {
        if (mViewHolder == null) {
            return;
        }
        if (input != null) {
            int width = input.getWidth();
            setPlayerWidth(width);
            mMediaNotifView.measure(input.getWidthMeasureSpec(), input.getHeightMeasureSpec());
            mViewHolder.getPlayer().measure(input.getWidthMeasureSpec(),
                    input.getHeightMeasureSpec());
        }
    }

    public void setPlayerWidth(int width) {
        ConstraintSet expandedSet = mMediaNotifView.getConstraintSet(R.id.expanded);
        ConstraintSet collapsedSet = mMediaNotifView.getConstraintSet(R.id.collapsed);
        if (mViewHolder == null) {
            return;
        }
        MotionLayout view = mViewHolder.getPlayer();
        ConstraintSet expandedSet = view.getConstraintSet(R.id.expanded);
        ConstraintSet collapsedSet = view.getConstraintSet(R.id.collapsed);
        collapsedSet.setGuidelineBegin(R.id.view_width, width);
        expandedSet.setGuidelineBegin(R.id.view_width, width);
        mMediaNotifView.updateState(R.id.collapsed, collapsedSet);
        mMediaNotifView.updateState(R.id.expanded, expandedSet);
        view.updateState(R.id.collapsed, collapsedSet);
        view.updateState(R.id.expanded, expandedSet);
    }

    public void animatePendingSizeChange(long duration, long startDelay) {
+53 −41
Original line number Diff line number Diff line
@@ -56,8 +56,13 @@ class MediaViewManager @Inject constructor(
            }
        }
    private val scrollChangedListener = object : View.OnScrollChangeListener {
        override fun onScrollChange(v: View?, scrollX: Int, scrollY: Int, oldScrollX: Int,
                                    oldScrollY: Int) {
        override fun onScrollChange(
            v: View?,
            scrollX: Int,
            scrollY: Int,
            oldScrollX: Int,
            oldScrollY: Int
        ) {
            if (playerWidthPlusPadding == 0) {
                return
            }
@@ -79,16 +84,17 @@ class MediaViewManager @Inject constructor(
            override fun onMediaDataRemoved(key: String) {
                val removed = mediaPlayers.remove(key)
                removed?.apply {
                    val beforeActive = mediaContent.indexOfChild(removed.view) <= activeMediaIndex
                    mediaContent.removeView(removed.view)
                    val beforeActive = mediaContent.indexOfChild(removed.view?.player) <=
                            activeMediaIndex
                    mediaContent.removeView(removed.view?.player)
                    removed.onDestroy()
                    updateMediaPaddings()
                    if (beforeActive) {
                        // also update the index here since the scroll below might not always lead
                        // to a scrolling changed
                        activeMediaIndex = Math.max(0, activeMediaIndex - 1)
                        mediaCarousel.scrollX = Math.max(mediaCarousel.scrollX
                                - playerWidthPlusPadding, 0)
                        mediaCarousel.scrollX = Math.max(mediaCarousel.scrollX -
                                playerWidthPlusPadding, 0)
                    }
                    updatePlayerVisibilities()
                }
@@ -103,7 +109,7 @@ class MediaViewManager @Inject constructor(

    private fun reorderAllPlayers() {
        for (mediaPlayer in mediaPlayers.values) {
            val view = mediaPlayer.view
            val view = mediaPlayer.view?.player
            if (mediaPlayer.isPlaying && mediaContent.indexOfChild(view) != 0) {
                mediaContent.removeView(view)
                mediaContent.addView(view, 0)
@@ -142,24 +148,26 @@ class MediaViewManager @Inject constructor(
            val routeManager = LocalMediaManager(context, localBluetoothManager,
                    imm, data.packageName)

            existingPlayer = MediaControlPanel(context, mediaContent, routeManager,
                    foregroundExecutor, backgroundExecutor, activityStarter)
            existingPlayer = MediaControlPanel(context, routeManager, foregroundExecutor,
                    backgroundExecutor, activityStarter)
            existingPlayer.attach(PlayerViewHolder.create(LayoutInflater.from(context),
                    mediaContent))
            mediaPlayers[key] = existingPlayer
            val lp = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT)
            existingPlayer.view.setLayoutParams(lp)
            existingPlayer.view?.player?.setLayoutParams(lp)
            existingPlayer.setListening(currentlyExpanded)
            if (existingPlayer.isPlaying) {
                mediaContent.addView(existingPlayer.view, 0)
                mediaContent.addView(existingPlayer.view?.player, 0)
            } else {
                mediaContent.addView(existingPlayer.view)
                mediaContent.addView(existingPlayer.view?.player)
            }
            updatePlayerToCurrentState(existingPlayer)
        } else if (existingPlayer.isPlaying &&
                    mediaContent.indexOfChild(existingPlayer.view) != 0) {
                    mediaContent.indexOfChild(existingPlayer.view?.player) != 0) {
            if (visualStabilityManager.isReorderingAllowed) {
                mediaContent.removeView(existingPlayer.view)
                mediaContent.addView(existingPlayer.view, 0)
                mediaContent.removeView(existingPlayer.view?.player)
                mediaContent.addView(existingPlayer.view?.player, 0)
            } else {
                visualStabilityManager.addReorderingAllowedCallback(visualStabilityCallback)
            }
@@ -167,7 +175,7 @@ class MediaViewManager @Inject constructor(
        existingPlayer.bind(data)
        // Resetting the progress to make sure it's taken into account for the latest
        // motion model
        existingPlayer.view.progress = currentState?.expansion ?: 0.0f
        existingPlayer.view?.player?.progress = currentState?.expansion ?: 0.0f
        updateMediaPaddings()
    }

@@ -190,7 +198,6 @@ class MediaViewManager @Inject constructor(
                mediaView.layoutParams = layoutParams
            }
        }

    }

    /**
@@ -201,8 +208,8 @@ class MediaViewManager @Inject constructor(
        currentState = state
        currentlyExpanded = state.expansion > 0
        for (mediaPlayer in mediaPlayers.values) {
            val view = mediaPlayer.view
            view.progress = state.expansion
            val view = mediaPlayer.view?.player
            view?.progress = state.expansion
        }
    }

@@ -215,8 +222,12 @@ class MediaViewManager @Inject constructor(
     * @param desiredState the target state we're transitioning to
     * @param animate should this be animated
     */
    fun onDesiredLocationChanged(desiredState: MediaState?, animate: Boolean, duration: Long,
                                 startDelay: Long) {
    fun onDesiredLocationChanged(
        desiredState: MediaState?,
        animate: Boolean,
        duration: Long,
        startDelay: Long
    ) {
        if (desiredState is MediaHost.MediaHostState) {
            // This is a hosting view, let's remeasure our players
            this.desiredState = desiredState
@@ -224,7 +235,7 @@ class MediaViewManager @Inject constructor(
            if (playerWidth != width) {
                setPlayerWidth(width)
                for (mediaPlayer in mediaPlayers.values) {
                    if (animate && mediaPlayer.view.visibility == View.VISIBLE) {
                    if (animate && mediaPlayer.view?.player?.visibility == View.VISIBLE) {
                        mediaPlayer.animatePendingSizeChange(duration, startDelay)
                    }
                }
@@ -268,22 +279,23 @@ class MediaViewManager @Inject constructor(
     */
    fun obtainMeasurement(input: MediaMeasurementInput): MeasurementOutput? {
        val firstPlayer = mediaPlayers.values.firstOrNull() ?: return null
        var result: MeasurementOutput? = null
        firstPlayer.view?.player?.let {
            // Let's measure the size of the first player and return its height
        val previousProgress = firstPlayer.view.progress
        val previousRight = firstPlayer.view.right
        val previousBottom = firstPlayer.view.bottom
        firstPlayer.view.progress = input.expansion
            val previousProgress = it.progress
            val previousRight = it.right
            val previousBottom = it.bottom
            it.progress = input.expansion
            firstPlayer.measure(input)
            // Relayouting is necessary in motionlayout to obtain its size properly ....
        firstPlayer.view.layout(0, 0, firstPlayer.view.measuredWidth,
                firstPlayer.view.measuredHeight)
        val result = MeasurementOutput(firstPlayer.view.measuredWidth,
                firstPlayer.view.measuredHeight)
        firstPlayer.view.progress = previousProgress
            it.layout(0, 0, it.measuredWidth, it.measuredHeight)
            val result = MeasurementOutput(it.measuredWidth, it.measuredHeight)
            it.progress = previousProgress
            if (desiredState != null) {
                // remeasure it to the old size again!
                firstPlayer.measure(desiredState!!.measurementInput)
            firstPlayer.view.layout(0, 0, previousRight, previousBottom)
                it.layout(0, 0, previousRight, previousBottom)
            }
        }
        return result
    }
@@ -295,7 +307,7 @@ class MediaViewManager @Inject constructor(
            val widthSpec = desiredState!!.measurementInput?.widthMeasureSpec ?: 0
            val heightSpec = desiredState!!.measurementInput?.heightMeasureSpec ?: 0
            for (mediaPlayer in mediaPlayers.values) {
                mediaPlayer.view.measure(widthSpec, heightSpec)
                mediaPlayer.view?.player?.measure(widthSpec, heightSpec)
            }
        }
    }
+91 −0

File added.

Preview size limit exceeded, changes collapsed.