Monica Ivan
Monica Ivan

Reputation: 162

Jetpack Compose - Media3 Exoplayer fills controller overlay but not artwork

I'm building a video player using the latest media3 Exoplayer, using Jetpack Compose:

The issue I am facing is that if I set the PlayerView to fullscreen

AndroidView(modifier = Modifier.fillMaxSize(),...)

the video will be stretched upon first opening it (or navigating to it via next()/previous()):

stretched full screen

However, if I flip the orientation it displays correctly, and then displays correctly when I flip it back:

correct full screen

This is how I ultimately want it to look. My Code:

Scaffold(
        topBar = { MyAppBar() },
        content = { innerPadding ->
            viewModel.openMediaFile(mediaFile)
            Box(
                modifier = Modifier
                    .fillMaxSize()
                    .padding(innerPadding)
                    .background(MyTheme.colors.background),
                contentAlignment = Alignment.Center
            ) {

                AndroidView(
                    modifier = Modifier.fillMaxSize(),
                    factory = { context ->
                        PlayerView(context).apply {
                            player = viewModel.player
                            artworkDisplayMode = PlayerView.ARTWORK_DISPLAY_MODE_FIT
                            artworkPlaceHolder?.let { defaultArtwork = it }
                        }
                    }
                )
            }
        },
    )

If I don't set

AndroidView(modifier = Modifier.fillMaxSize(),...)

it just looks bad, as I would like the overlay to fill the entire screen.

bad version

What I've tried:

  1. artworkDisplayMode = PlayerView.ARTWORK_DISPLAY_MODE_FIT in the PlayerView block in Compose,
  2. instantiating the player with
ExoPlayer.Builder(context)
            .setVideoScalingMode(C.VIDEO_SCALING_MODE_SCALE_TO_FIT)
            .build()
  1. using
layoutParams = FrameLayout.LayoutParams(
                                    ViewGroup.LayoutParams.MATCH_PARENT,
                                    ViewGroup.LayoutParams.MATCH_PARENT
                                )

What I'm trying to achieve is a full screen layout with a fitted video.

Upvotes: 3

Views: 1541

Answers (1)

ryankuck
ryankuck

Reputation: 848

Since you are using a viewModel to store the player, you are most likely preserving the same player between different videos.

Based on the AndroidView docs you can use the update method to fix this:

            // Adds view to Compose
            Box(
                modifier = Modifier
                    .fillMaxSize()
                    .padding(50.dp),
                contentAlignment = Alignment.Center
            ) {
                AndroidView(
                    modifier = Modifier.fillMaxSize(),
                    factory = { context ->
                        PlayerView(context)
                    },
                    update = { view ->
                        val newPlayer = ExoPlayer.Builder(view.context)
                            .build()

                        val mediaItem = MediaItem.fromUri("https://upload.wikimedia.org/wikipedia/commons/transcoded/e/e0/Abstract_Music_Animation_%22Defend_the_Yellow_River%22.webm/Abstract_Music_Animation_%22Defend_the_Yellow_River%22.webm.360p.webm")
                        newPlayer.setMediaItem(mediaItem)
                        newPlayer.prepare()

                        view.apply {
                            player = newPlayer
                        }
                    }
                )
            }

Result on first load:

Result

Upvotes: 1

Related Questions