From 6b614fab2c6b7e6eef7def857e7a22ec2f9cc8df Mon Sep 17 00:00:00 2001 From: Mattias Buelens Date: Wed, 1 Apr 2026 17:52:59 +0200 Subject: [PATCH 1/2] Update play/pause icons --- common/src/main/res/drawable/ic_pause.xml | 9 +++++---- common/src/main/res/drawable/ic_play.xml | 9 +++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/common/src/main/res/drawable/ic_pause.xml b/common/src/main/res/drawable/ic_pause.xml index bb28a6c..c0ce4d5 100644 --- a/common/src/main/res/drawable/ic_pause.xml +++ b/common/src/main/res/drawable/ic_pause.xml @@ -1,9 +1,10 @@ + android:tint="?attr/colorControlNormal" + android:viewportWidth="960" + android:viewportHeight="960"> + android:fillColor="@android:color/black" + android:pathData="M560,760L560,200L720,200L720,760L560,760ZM240,760L240,200L400,200L400,760L240,760Z" /> diff --git a/common/src/main/res/drawable/ic_play.xml b/common/src/main/res/drawable/ic_play.xml index bf9b895..5e68373 100644 --- a/common/src/main/res/drawable/ic_play.xml +++ b/common/src/main/res/drawable/ic_play.xml @@ -1,9 +1,10 @@ + android:tint="?attr/colorControlNormal" + android:viewportWidth="960" + android:viewportHeight="960"> + android:fillColor="@android:color/black" + android:pathData="M320,760L320,200L760,480L320,760Z" /> From ace6f15df499928be7682de2f39217cfa6a39ebc Mon Sep 17 00:00:00 2001 From: Mattias Buelens Date: Wed, 1 Apr 2026 18:18:31 +0200 Subject: [PATCH 2/2] Rewrite CustomFullScreenActivity using Compose --- .../ui/fullscreen/CustomFullScreenActivity.kt | 145 +++++++++++++----- .../main/res/layout/activity_fullscreen.xml | 24 --- 2 files changed, 107 insertions(+), 62 deletions(-) delete mode 100644 full-screen-handling/src/main/res/layout/activity_fullscreen.xml diff --git a/full-screen-handling/src/main/java/com/theoplayer/sample/ui/fullscreen/CustomFullScreenActivity.kt b/full-screen-handling/src/main/java/com/theoplayer/sample/ui/fullscreen/CustomFullScreenActivity.kt index e313d5f..878f622 100644 --- a/full-screen-handling/src/main/java/com/theoplayer/sample/ui/fullscreen/CustomFullScreenActivity.kt +++ b/full-screen-handling/src/main/java/com/theoplayer/sample/ui/fullscreen/CustomFullScreenActivity.kt @@ -1,70 +1,139 @@ package com.theoplayer.sample.ui.fullscreen import android.os.Bundle -import android.view.LayoutInflater import android.view.ViewGroup -import com.google.android.material.button.MaterialButton +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.FilledIconButton +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.darkColorScheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.ComposeView +import androidx.compose.ui.res.dimensionResource +import androidx.compose.ui.res.painterResource +import com.theoplayer.android.api.event.EventListener +import com.theoplayer.android.api.event.player.PlayerEvent import com.theoplayer.android.api.event.player.PlayerEventTypes import com.theoplayer.android.api.fullscreen.FullScreenActivity import com.theoplayer.android.api.fullscreen.FullScreenManager import com.theoplayer.android.api.player.Player class CustomFullScreenActivity : FullScreenActivity() { - private lateinit var playPauseButton: MaterialButton private lateinit var theoPlayer: Player private lateinit var theoFullScreenManager: FullScreenManager override fun onCreate(savedInstanceState: Bundle?) { - // Adding support for extended AppCompat features. - // It allows to use styles and themes defined for material components. - delegate.installViewFactory() - delegate.onCreate(savedInstanceState) super.onCreate(savedInstanceState) - // Inflating custom view. - val view = LayoutInflater.from(this).inflate(R.layout.activity_fullscreen, null, false) - delegate.addContentView( - view, + // Gathering THEO objects references. + theoPlayer = theOplayerView!!.player + theoFullScreenManager = theOplayerView!!.fullScreenManager + + // Add custom overlay. + addContentView( + ComposeView(this).apply { + setContent { + MaterialTheme(colorScheme = darkColorScheme()) { + FullScreenOverlay( + player = theoPlayer, + fullScreenManager = theoFullScreenManager + ) + } + } + }, ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT ) ) + } +} - // Gathering THEO objects references. - theoPlayer = theOplayerView!!.player - theoFullScreenManager = theOplayerView!!.fullScreenManager - - // Configuring UI behavior. - playPauseButton = view.findViewById(R.id.playPauseButton) - val exitFullScreenButton = view.findViewById(R.id.exitFullScreenButton) - - adjustPlayPauseButtonIcon() - playPauseButton.setOnClickListener { onPlayPauseClick() } - exitFullScreenButton.setOnClickListener { onFullScreenExit() } - - // Configuring THEOplayer. - theoPlayer.addEventListener(PlayerEventTypes.PLAY) { adjustPlayPauseButtonIcon() } - theoPlayer.addEventListener(PlayerEventTypes.PAUSE) { adjustPlayPauseButtonIcon() } +@Composable +fun FullScreenOverlay( + player: Player, + fullScreenManager: FullScreenManager +) { + val spaceMargin = dimensionResource(com.theoplayer.sample.common.R.dimen.spaceMargin) + Row( + modifier = Modifier.padding(spaceMargin), + horizontalArrangement = Arrangement.spacedBy(spaceMargin) + ) { + PlayButton(player = player) + ExitFullscreenButton(fullScreenManager = fullScreenManager) } +} - private fun onFullScreenExit() { - theoFullScreenManager.exitFullScreen() +@Composable +fun PlayButton( + modifier: Modifier = Modifier, + player: Player +) { + val paused = rememberPaused(player) + FilledIconButton( + modifier = modifier, + onClick = { + if (player.isPaused) { + player.play() + } else { + player.pause() + } + } + ) { + Icon( + painter = painterResource( + if (paused) { + com.theoplayer.sample.common.R.drawable.ic_play + } else { + com.theoplayer.sample.common.R.drawable.ic_pause + } + ), + contentDescription = if (paused) "Play" else "Pause" + ) } +} - private fun onPlayPauseClick() { - if (theoPlayer.isPaused) { - theoPlayer.play() - } else { - theoPlayer.pause() +@Composable +fun ExitFullscreenButton( + modifier: Modifier = Modifier, + fullScreenManager: FullScreenManager +) { + FilledIconButton( + modifier = modifier, + onClick = { + fullScreenManager.exitFullScreen() } + ) { + Icon( + painter = painterResource(com.theoplayer.sample.common.R.drawable.ic_fullscreen_exit), + contentDescription = "Exit fullscreen" + ) } +} - private fun adjustPlayPauseButtonIcon() { - if (theoPlayer.isPaused) { - playPauseButton.setIconResource(com.theoplayer.sample.common.R.drawable.ic_play) - } else { - playPauseButton.setIconResource(com.theoplayer.sample.common.R.drawable.ic_pause) +/** + * Returns whether the player is [paused][Player.isPaused]. + * Updates automatically. + */ +@Composable +fun rememberPaused(player: Player): Boolean { + var paused by remember { mutableStateOf(player.isPaused) } + DisposableEffect(player) { + val listener = EventListener> { paused = player.isPaused } + player.addEventListener(PlayerEventTypes.PLAY, listener) + player.addEventListener(PlayerEventTypes.PAUSE, listener) + onDispose { + player.removeEventListener(PlayerEventTypes.PLAY, listener) + player.removeEventListener(PlayerEventTypes.PAUSE, listener) } } + return paused } diff --git a/full-screen-handling/src/main/res/layout/activity_fullscreen.xml b/full-screen-handling/src/main/res/layout/activity_fullscreen.xml deleted file mode 100644 index f440d6e..0000000 --- a/full-screen-handling/src/main/res/layout/activity_fullscreen.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - -