Chore/rework fullscreen configuration (#4142)
* feat(android): handle navigation bar status in full-screen mode * chore: update default value of prop * chore(android): rework fullscreen configuration --------- Co-authored-by: mostafahasani <seyedmostafahassani@gmail.com>
This commit is contained in:
@@ -7,6 +7,8 @@ class ControlsConfig {
|
||||
var hideSeekBar: Boolean = false
|
||||
var seekIncrementMS: Int = 10000
|
||||
var hideDuration: Boolean = false
|
||||
var hideNavigationBarOnFullScreenMode: Boolean = true
|
||||
var hideNotificationBarOnFullScreenMode: Boolean = true
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
@@ -17,8 +19,9 @@ class ControlsConfig {
|
||||
config.hideSeekBar = ReactBridgeUtils.safeGetBool(src, "hideSeekBar", false)
|
||||
config.seekIncrementMS = ReactBridgeUtils.safeGetInt(src, "seekIncrementMS", 10000)
|
||||
config.hideDuration = ReactBridgeUtils.safeGetBool(src, "hideDuration", false)
|
||||
config.hideNavigationBarOnFullScreenMode = ReactBridgeUtils.safeGetBool(src, "hideNavigationBarOnFullScreenMode", true)
|
||||
config.hideNotificationBarOnFullScreenMode = ReactBridgeUtils.safeGetBool(src, "hideNotificationBarOnFullScreenMode", true)
|
||||
}
|
||||
|
||||
return config
|
||||
}
|
||||
}
|
||||
|
@@ -6,11 +6,16 @@ import android.content.Context
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.view.ViewGroup
|
||||
import android.view.Window
|
||||
import android.view.WindowManager
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.ImageButton
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.core.view.WindowInsetsControllerCompat
|
||||
import androidx.media3.ui.LegacyPlayerControlView
|
||||
import com.brentvatne.common.api.ControlsConfig
|
||||
import com.brentvatne.common.toolbox.DebugLog
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
@@ -20,14 +25,22 @@ class FullScreenPlayerView(
|
||||
private val exoPlayerView: ExoPlayerView,
|
||||
private val reactExoplayerView: ReactExoplayerView,
|
||||
private val playerControlView: LegacyPlayerControlView?,
|
||||
private val onBackPressedCallback: OnBackPressedCallback
|
||||
) : Dialog(context, android.R.style.Theme_Black_NoTitleBar_Fullscreen) {
|
||||
private val onBackPressedCallback: OnBackPressedCallback,
|
||||
private val controlsConfig: ControlsConfig
|
||||
) : Dialog(context, android.R.style.Theme_Black_NoTitleBar) {
|
||||
|
||||
private var parent: ViewGroup? = null
|
||||
private val containerView = FrameLayout(context)
|
||||
private val mKeepScreenOnHandler = Handler(Looper.getMainLooper())
|
||||
private val mKeepScreenOnUpdater = KeepScreenOnUpdater(this)
|
||||
|
||||
// As this view is fullscreen we need to save initial state and restore it afterward
|
||||
// Following variables save UI state when open the view
|
||||
// restoreUIState, will reapply these values
|
||||
private var initialSystemBarsBehavior: Int? = null
|
||||
private var initialNavigationBarIsVisible: Boolean? = null
|
||||
private var initialNotificationBarIsVisible: Boolean? = null
|
||||
|
||||
private class KeepScreenOnUpdater(fullScreenPlayerView: FullScreenPlayerView) : Runnable {
|
||||
private val mFullscreenPlayer = WeakReference(fullScreenPlayerView)
|
||||
|
||||
@@ -59,6 +72,15 @@ class FullScreenPlayerView(
|
||||
|
||||
init {
|
||||
setContentView(containerView, generateDefaultLayoutParams())
|
||||
|
||||
window?.let {
|
||||
val inset = WindowInsetsControllerCompat(it, it.decorView)
|
||||
initialSystemBarsBehavior = inset.systemBarsBehavior
|
||||
initialNavigationBarIsVisible = ViewCompat.getRootWindowInsets(it.decorView)
|
||||
?.isVisible(WindowInsetsCompat.Type.navigationBars()) == true
|
||||
initialNotificationBarIsVisible = ViewCompat.getRootWindowInsets(it.decorView)
|
||||
?.isVisible(WindowInsetsCompat.Type.statusBars()) == true
|
||||
}
|
||||
}
|
||||
override fun onBackPressed() {
|
||||
super.onBackPressed()
|
||||
@@ -75,6 +97,7 @@ class FullScreenPlayerView(
|
||||
parent?.removeView(it)
|
||||
containerView.addView(it, generateDefaultLayoutParams())
|
||||
}
|
||||
updateNavigationBarVisibility()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
@@ -89,6 +112,19 @@ class FullScreenPlayerView(
|
||||
}
|
||||
parent?.requestLayout()
|
||||
parent = null
|
||||
restoreSystemUI()
|
||||
}
|
||||
|
||||
// restore system UI state
|
||||
private fun restoreSystemUI() {
|
||||
window?.let {
|
||||
updateNavigationBarVisibility(
|
||||
it,
|
||||
initialNavigationBarIsVisible,
|
||||
initialNotificationBarIsVisible,
|
||||
initialSystemBarsBehavior
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getFullscreenIconResource(isFullscreen: Boolean): Int =
|
||||
@@ -127,4 +163,61 @@ class FullScreenPlayerView(
|
||||
layoutParams.setMargins(0, 0, 0, 0)
|
||||
return layoutParams
|
||||
}
|
||||
|
||||
private fun updateBarVisibility(
|
||||
inset: WindowInsetsControllerCompat,
|
||||
type: Int,
|
||||
shouldHide: Boolean?,
|
||||
initialVisibility: Boolean?,
|
||||
systemBarsBehavior: Int? = null
|
||||
) {
|
||||
shouldHide?.takeIf { it != initialVisibility }?.let {
|
||||
if (it) {
|
||||
inset.hide(type)
|
||||
systemBarsBehavior?.let { behavior -> inset.systemBarsBehavior = behavior }
|
||||
} else {
|
||||
inset.show(type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Move the UI to fullscreen.
|
||||
// if you change this code, remember to check that the UI is well restored in restoreUIState
|
||||
private fun updateNavigationBarVisibility(
|
||||
window: Window,
|
||||
hideNavigationBarOnFullScreenMode: Boolean?,
|
||||
hideNotificationBarOnFullScreenMode: Boolean?,
|
||||
systemBarsBehavior: Int?
|
||||
) {
|
||||
// Configure the behavior of the hidden system bars.
|
||||
val inset = WindowInsetsControllerCompat(window, window.decorView)
|
||||
|
||||
// Update navigation bar visibility and apply systemBarsBehavior if hiding
|
||||
updateBarVisibility(
|
||||
inset,
|
||||
WindowInsetsCompat.Type.navigationBars(),
|
||||
hideNavigationBarOnFullScreenMode,
|
||||
initialNavigationBarIsVisible,
|
||||
systemBarsBehavior
|
||||
)
|
||||
|
||||
// Update notification bar visibility (no need for systemBarsBehavior here)
|
||||
updateBarVisibility(
|
||||
inset,
|
||||
WindowInsetsCompat.Type.statusBars(),
|
||||
hideNotificationBarOnFullScreenMode,
|
||||
initialNotificationBarIsVisible
|
||||
)
|
||||
}
|
||||
|
||||
private fun updateNavigationBarVisibility() {
|
||||
window?.let {
|
||||
updateNavigationBarVisibility(
|
||||
it,
|
||||
controlsConfig.hideNavigationBarOnFullScreenMode,
|
||||
controlsConfig.hideNotificationBarOnFullScreenMode,
|
||||
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -427,15 +427,6 @@ public class ReactExoplayerView extends FrameLayout implements
|
||||
});
|
||||
}
|
||||
|
||||
if (fullScreenPlayerView == null) {
|
||||
fullScreenPlayerView = new FullScreenPlayerView(getContext(), exoPlayerView, this, playerControlView, new OnBackPressedCallback(true) {
|
||||
@Override
|
||||
public void handleOnBackPressed() {
|
||||
setFullscreen(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Setting the player for the playerControlView
|
||||
playerControlView.setPlayer(player);
|
||||
playPauseControlContainer = playerControlView.findViewById(R.id.exo_play_pause_container);
|
||||
@@ -2261,6 +2252,12 @@ public class ReactExoplayerView extends FrameLayout implements
|
||||
}
|
||||
|
||||
if (isFullscreen) {
|
||||
fullScreenPlayerView = new FullScreenPlayerView(getContext(), exoPlayerView, this, playerControlView, new OnBackPressedCallback(true) {
|
||||
@Override
|
||||
public void handleOnBackPressed() {
|
||||
setFullscreen(false);
|
||||
}
|
||||
}, controlsConfig);
|
||||
eventEmitter.onVideoFullscreenPlayerWillPresent.invoke();
|
||||
if (fullScreenPlayerView != null) {
|
||||
fullScreenPlayerView.show();
|
||||
@@ -2383,4 +2380,4 @@ public class ReactExoplayerView extends FrameLayout implements
|
||||
controlsConfig = controlsStyles;
|
||||
refreshProgressBarVisibility();
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user