From 7f9dbca23d6055289f3a85a39ff2658264339e09 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Mon, 21 Sep 2026 13:03:40 +0200 Subject: [PATCH 1/6] feat(video): full screen gesture Signed-off-by: alperozturk96 --- .../client/player/ui/PlayerActivity.kt | 11 ++-- .../nextcloud/client/player/ui/PlayerView.kt | 54 +++++++++++++++++++ .../client/player/ui/video/VideoPlayerView.kt | 27 ++++------ .../ui/preview/PreviewPlaybackFragment.kt | 33 +++++++++++- 4 files changed, 100 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/com/nextcloud/client/player/ui/PlayerActivity.kt b/app/src/main/java/com/nextcloud/client/player/ui/PlayerActivity.kt index 751f465c34c3..198874a2b321 100644 --- a/app/src/main/java/com/nextcloud/client/player/ui/PlayerActivity.kt +++ b/app/src/main/java/com/nextcloud/client/player/ui/PlayerActivity.kt @@ -139,12 +139,11 @@ class PlayerActivity : override fun onConfigurationChanged(newConfig: Configuration) { super.onConfigurationChanged(newConfig) - val videoPlayerView = playerView as? VideoPlayerView ?: return - if (isInPictureInPictureMode) { - videoPlayerView.hideControls() - } else { - videoPlayerView.showControls() + if (!isInPictureInPictureMode) { + return } + + playerView.hideControls() } override fun onUserLeaveHint() { @@ -172,7 +171,7 @@ class PlayerActivity : } if (!isInPictureInPictureMode) { - (playerView as? VideoPlayerView)?.showControls() + playerView.showControls() } } diff --git a/app/src/main/java/com/nextcloud/client/player/ui/PlayerView.kt b/app/src/main/java/com/nextcloud/client/player/ui/PlayerView.kt index eb632ca452a7..25c412281320 100644 --- a/app/src/main/java/com/nextcloud/client/player/ui/PlayerView.kt +++ b/app/src/main/java/com/nextcloud/client/player/ui/PlayerView.kt @@ -9,6 +9,8 @@ package com.nextcloud.client.player.ui import android.content.Context import android.util.AttributeSet +import android.view.GestureDetector +import android.view.MotionEvent import android.widget.LinearLayout import androidx.annotation.CallSuper import androidx.annotation.LayoutRes @@ -26,6 +28,7 @@ import com.nextcloud.client.player.model.state.PlaybackState import com.nextcloud.client.player.ui.control.PlayerControlView import com.nextcloud.client.player.ui.pager.PlayerPager import com.nextcloud.client.player.util.WindowWrapper +import com.nextcloud.utils.extensions.setVisibilityWithAnimation import com.owncloud.android.R import com.owncloud.android.datamodel.FileDataStorageManager import com.owncloud.android.lib.common.OwnCloudClientManagerFactory @@ -69,6 +72,19 @@ abstract class PlayerView @JvmOverloads constructor( var onMoreClick: (() -> Unit)? = null + protected var isFullScreen = false + private set + + private val tapDetector = GestureDetector( + context, + object : GestureDetector.SimpleOnGestureListener() { + override fun onSingleTapUp(event: MotionEvent): Boolean { + onTap(event) + return false + } + } + ) + init { inflate(context, layoutRes, this) if (!isInEditMode) { @@ -87,6 +103,44 @@ abstract class PlayerView @JvmOverloads constructor( } } + override fun onInterceptTouchEvent(event: MotionEvent): Boolean { + tapDetector.onTouchEvent(event) + return super.onInterceptTouchEvent(event) + } + + protected open fun onTap(event: MotionEvent) { + when { + isFullScreen -> showControls() + isTouchOnMedia(event) -> hideControls() + } + } + + protected fun isTouchOnMedia(event: MotionEvent): Boolean = event.y > topBar.bottom && event.y < playerControlView.y + + @CallSuper + open fun showControls() { + windowWrapper.showSystemBars() + if (!isFullScreen) { + return + } + + isFullScreen = false + topBar.setVisibilityWithAnimation(true) + playerControlView.setVisibilityWithAnimation(true) + } + + @CallSuper + open fun hideControls() { + windowWrapper.hideSystemBars() + if (isFullScreen) { + return + } + + isFullScreen = true + topBar.setVisibilityWithAnimation(false) + playerControlView.setVisibilityWithAnimation(false) + } + protected fun applyTopBarInsets(insets: Insets) { val actionInset = resources.getDimensionPixelSize(R.dimen.standard_quarter_padding) topBar.setPadding(insets.left, insets.top, insets.right + actionInset, 0) diff --git a/app/src/main/java/com/nextcloud/client/player/ui/video/VideoPlayerView.kt b/app/src/main/java/com/nextcloud/client/player/ui/video/VideoPlayerView.kt index 125e3e9890ba..3ee05b266352 100644 --- a/app/src/main/java/com/nextcloud/client/player/ui/video/VideoPlayerView.kt +++ b/app/src/main/java/com/nextcloud/client/player/ui/video/VideoPlayerView.kt @@ -12,7 +12,6 @@ import android.view.MotionEvent import android.view.WindowInsets import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat.Type -import androidx.core.view.isVisible import androidx.fragment.app.Fragment import androidx.lifecycle.lifecycleScope import com.nextcloud.client.player.model.file.PlaybackFile @@ -65,29 +64,21 @@ class VideoPlayerView(context: Context) : PlayerView(context) { return WindowInsetsCompat.CONSUMED.toWindowInsets() } - override fun dispatchTouchEvent(event: MotionEvent): Boolean { - if (event.action == MotionEvent.ACTION_DOWN) { - val isTouchOutsideControls = event.y < playerControlView.y && event.y > topBar.height - when { - !playerControlView.isVisible -> showControls() - isTouchOutsideControls -> hideControls() - else -> restartHideControlsTimer() - } + override fun onTap(event: MotionEvent) { + when { + isFullScreen -> showControls() + isTouchOnMedia(event) -> hideControls() + else -> restartHideControlsTimer() } - return super.dispatchTouchEvent(event) } - fun showControls() { - windowWrapper.showSystemBars() - topBar.visibility = VISIBLE - playerControlView.visibility = VISIBLE + override fun showControls() { + super.showControls() restartHideControlsTimer() } - fun hideControls() { - windowWrapper.hideSystemBars() - topBar.visibility = GONE - playerControlView.visibility = GONE + override fun hideControls() { + super.hideControls() cancelHideControlsTimer() } diff --git a/app/src/main/java/com/owncloud/android/ui/preview/PreviewPlaybackFragment.kt b/app/src/main/java/com/owncloud/android/ui/preview/PreviewPlaybackFragment.kt index 9da820b28125..8134633f1835 100644 --- a/app/src/main/java/com/owncloud/android/ui/preview/PreviewPlaybackFragment.kt +++ b/app/src/main/java/com/owncloud/android/ui/preview/PreviewPlaybackFragment.kt @@ -19,6 +19,9 @@ import androidx.activity.addCallback import androidx.core.content.ContextCompat import androidx.core.os.bundleOf import androidx.core.view.MenuProvider +import androidx.core.view.WindowCompat +import androidx.core.view.WindowInsetsCompat +import androidx.core.view.WindowInsetsControllerCompat import androidx.core.view.isVisible import androidx.fragment.app.Fragment import androidx.lifecycle.Lifecycle @@ -42,6 +45,7 @@ import com.nextcloud.ui.fileactions.FileAction import com.nextcloud.ui.fileactions.FileActionsBottomSheet import com.nextcloud.utils.extensions.getParcelableArgument import com.nextcloud.utils.extensions.getSerializableArgument +import com.nextcloud.utils.extensions.setVisibilityWithAnimation import com.owncloud.android.R import com.owncloud.android.databinding.PreviewPlaybackFragmentBinding import com.owncloud.android.datamodel.OCFile @@ -120,6 +124,7 @@ class PreviewPlaybackFragment : private var renderedVideoSize: VideoSize? = null private var pictureInPictureCallback: OnBackPressedCallback? = null + private var isFullScreen = false override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -138,6 +143,8 @@ class PreviewPlaybackFragment : loadThumbnail() registerPictureInPictureOnBack() binding.playerControlView.navigator = activity as? MediaNavigator + isFullScreen = previewActivity()?.isSystemUIVisible == false + binding.surfaceView.setOnClickListener { toggleFullScreen() } updatePlayerControlsVisibility() binding.root.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ -> if (ownsPlayback(binding.surfaceView)) render(playbackModel.state) @@ -399,8 +406,32 @@ class PreviewPlaybackFragment : private fun isInPictureInPictureMode(): Boolean = activity?.isInPictureInPictureMode == true + private fun toggleFullScreen() { + val previewActivity = previewActivity() ?: return + isFullScreen = !isFullScreen + + previewActivity.toggleActionBarVisibility(isFullScreen) + binding.playerControlView.setVisibilityWithAnimation(!isFullScreen) + + val insetsController = WindowCompat.getInsetsController(previewActivity.window, binding.root) + if (isFullScreen) { + insetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE + insetsController.hide(WindowInsetsCompat.Type.systemBars()) + } else { + insetsController.show(WindowInsetsCompat.Type.systemBars()) + } + } + private fun updatePlayerControlsVisibility() { - binding.playerControlView.isVisible = !isInPictureInPictureMode() + if (isInPictureInPictureMode()) { + binding.playerControlView.isVisible = false + return + } + + // playback updates arrive every second, so they must not undo full screen or cut the fade short + if (!isFullScreen) { + binding.playerControlView.isVisible = true + } } private fun showVideo(videoSize: VideoSize?) { From f5185b98a71b0f0d4a78e545ddad7e8703dc0a22 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Mon, 21 Sep 2026 15:33:27 +0200 Subject: [PATCH 2/6] better variable names Signed-off-by: alperozturk96 --- .../com/nextcloud/client/player/ui/PlayerView.kt | 12 ++++++------ .../client/player/ui/video/VideoPlayerView.kt | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/nextcloud/client/player/ui/PlayerView.kt b/app/src/main/java/com/nextcloud/client/player/ui/PlayerView.kt index 25c412281320..ee90eb7168ac 100644 --- a/app/src/main/java/com/nextcloud/client/player/ui/PlayerView.kt +++ b/app/src/main/java/com/nextcloud/client/player/ui/PlayerView.kt @@ -72,7 +72,7 @@ abstract class PlayerView @JvmOverloads constructor( var onMoreClick: (() -> Unit)? = null - protected var isFullScreen = false + protected var shouldShowControls = false private set private val tapDetector = GestureDetector( @@ -110,7 +110,7 @@ abstract class PlayerView @JvmOverloads constructor( protected open fun onTap(event: MotionEvent) { when { - isFullScreen -> showControls() + shouldShowControls -> showControls() isTouchOnMedia(event) -> hideControls() } } @@ -120,11 +120,11 @@ abstract class PlayerView @JvmOverloads constructor( @CallSuper open fun showControls() { windowWrapper.showSystemBars() - if (!isFullScreen) { + if (!shouldShowControls) { return } - isFullScreen = false + shouldShowControls = false topBar.setVisibilityWithAnimation(true) playerControlView.setVisibilityWithAnimation(true) } @@ -132,11 +132,11 @@ abstract class PlayerView @JvmOverloads constructor( @CallSuper open fun hideControls() { windowWrapper.hideSystemBars() - if (isFullScreen) { + if (shouldShowControls) { return } - isFullScreen = true + shouldShowControls = true topBar.setVisibilityWithAnimation(false) playerControlView.setVisibilityWithAnimation(false) } diff --git a/app/src/main/java/com/nextcloud/client/player/ui/video/VideoPlayerView.kt b/app/src/main/java/com/nextcloud/client/player/ui/video/VideoPlayerView.kt index 3ee05b266352..a0641a694488 100644 --- a/app/src/main/java/com/nextcloud/client/player/ui/video/VideoPlayerView.kt +++ b/app/src/main/java/com/nextcloud/client/player/ui/video/VideoPlayerView.kt @@ -66,7 +66,7 @@ class VideoPlayerView(context: Context) : PlayerView(context) { override fun onTap(event: MotionEvent) { when { - isFullScreen -> showControls() + shouldShowControls -> showControls() isTouchOnMedia(event) -> hideControls() else -> restartHideControlsTimer() } From 50059659b6da3bd1b372ac2d7e63900c8e574f39 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Mon, 21 Sep 2026 16:42:03 +0200 Subject: [PATCH 3/6] remove unused code for entering and exiting full-screen Signed-off-by: alperozturk96 --- .../client/player/ui/PlayerActivity.kt | 17 +----- .../nextcloud/client/player/ui/PlayerView.kt | 54 ------------------- .../client/player/ui/video/VideoPlayerView.kt | 48 ----------------- 3 files changed, 2 insertions(+), 117 deletions(-) diff --git a/app/src/main/java/com/nextcloud/client/player/ui/PlayerActivity.kt b/app/src/main/java/com/nextcloud/client/player/ui/PlayerActivity.kt index 198874a2b321..6c1e6efe0979 100644 --- a/app/src/main/java/com/nextcloud/client/player/ui/PlayerActivity.kt +++ b/app/src/main/java/com/nextcloud/client/player/ui/PlayerActivity.kt @@ -136,16 +136,6 @@ class PlayerActivity : } } - override fun onConfigurationChanged(newConfig: Configuration) { - super.onConfigurationChanged(newConfig) - - if (!isInPictureInPictureMode) { - return - } - - playerView.hideControls() - } - override fun onUserLeaveHint() { super.onUserLeaveHint() if (canUsePictureInPictureMode()) { @@ -165,14 +155,11 @@ class PlayerActivity : null } + // Finish the activity if the user closes the PIP window if (!isInPictureInPictureMode && lifecycle.currentState == Lifecycle.State.CREATED) { - finish() // Finish the activity if the user closes the PIP window + finish() return } - - if (!isInPictureInPictureMode) { - playerView.showControls() - } } private fun canUsePictureInPictureMode(): Boolean = diff --git a/app/src/main/java/com/nextcloud/client/player/ui/PlayerView.kt b/app/src/main/java/com/nextcloud/client/player/ui/PlayerView.kt index ee90eb7168ac..eb632ca452a7 100644 --- a/app/src/main/java/com/nextcloud/client/player/ui/PlayerView.kt +++ b/app/src/main/java/com/nextcloud/client/player/ui/PlayerView.kt @@ -9,8 +9,6 @@ package com.nextcloud.client.player.ui import android.content.Context import android.util.AttributeSet -import android.view.GestureDetector -import android.view.MotionEvent import android.widget.LinearLayout import androidx.annotation.CallSuper import androidx.annotation.LayoutRes @@ -28,7 +26,6 @@ import com.nextcloud.client.player.model.state.PlaybackState import com.nextcloud.client.player.ui.control.PlayerControlView import com.nextcloud.client.player.ui.pager.PlayerPager import com.nextcloud.client.player.util.WindowWrapper -import com.nextcloud.utils.extensions.setVisibilityWithAnimation import com.owncloud.android.R import com.owncloud.android.datamodel.FileDataStorageManager import com.owncloud.android.lib.common.OwnCloudClientManagerFactory @@ -72,19 +69,6 @@ abstract class PlayerView @JvmOverloads constructor( var onMoreClick: (() -> Unit)? = null - protected var shouldShowControls = false - private set - - private val tapDetector = GestureDetector( - context, - object : GestureDetector.SimpleOnGestureListener() { - override fun onSingleTapUp(event: MotionEvent): Boolean { - onTap(event) - return false - } - } - ) - init { inflate(context, layoutRes, this) if (!isInEditMode) { @@ -103,44 +87,6 @@ abstract class PlayerView @JvmOverloads constructor( } } - override fun onInterceptTouchEvent(event: MotionEvent): Boolean { - tapDetector.onTouchEvent(event) - return super.onInterceptTouchEvent(event) - } - - protected open fun onTap(event: MotionEvent) { - when { - shouldShowControls -> showControls() - isTouchOnMedia(event) -> hideControls() - } - } - - protected fun isTouchOnMedia(event: MotionEvent): Boolean = event.y > topBar.bottom && event.y < playerControlView.y - - @CallSuper - open fun showControls() { - windowWrapper.showSystemBars() - if (!shouldShowControls) { - return - } - - shouldShowControls = false - topBar.setVisibilityWithAnimation(true) - playerControlView.setVisibilityWithAnimation(true) - } - - @CallSuper - open fun hideControls() { - windowWrapper.hideSystemBars() - if (shouldShowControls) { - return - } - - shouldShowControls = true - topBar.setVisibilityWithAnimation(false) - playerControlView.setVisibilityWithAnimation(false) - } - protected fun applyTopBarInsets(insets: Insets) { val actionInset = resources.getDimensionPixelSize(R.dimen.standard_quarter_padding) topBar.setPadding(insets.left, insets.top, insets.right + actionInset, 0) diff --git a/app/src/main/java/com/nextcloud/client/player/ui/video/VideoPlayerView.kt b/app/src/main/java/com/nextcloud/client/player/ui/video/VideoPlayerView.kt index a0641a694488..5bf1f4c34ee4 100644 --- a/app/src/main/java/com/nextcloud/client/player/ui/video/VideoPlayerView.kt +++ b/app/src/main/java/com/nextcloud/client/player/ui/video/VideoPlayerView.kt @@ -8,26 +8,16 @@ package com.nextcloud.client.player.ui.video import android.content.Context -import android.view.MotionEvent import android.view.WindowInsets import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat.Type import androidx.fragment.app.Fragment -import androidx.lifecycle.lifecycleScope import com.nextcloud.client.player.model.file.PlaybackFile import com.nextcloud.client.player.ui.PlayerView import com.owncloud.android.R import kotlinx.coroutines.Job -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch -import kotlin.time.Duration.Companion.milliseconds class VideoPlayerView(context: Context) : PlayerView(context) { - - companion object { - private const val HIDE_CONTROLS_DELAY = 5000L - } - override val layoutRes get() = R.layout.player_video_view override val createFragment: (PlaybackFile) -> Fragment get() = { VideoFileFragment.createInstance(it) } @@ -38,13 +28,6 @@ class VideoPlayerView(context: Context) : PlayerView(context) { topBar.setBackgroundResource(R.drawable.player_video_top_scrim) } - override fun onStart() { - super.onStart() - if (!activity.isInPictureInPictureMode) { - showControls() - } - } - override fun onStop() { super.onStop() cancelHideControlsTimer() @@ -64,37 +47,6 @@ class VideoPlayerView(context: Context) : PlayerView(context) { return WindowInsetsCompat.CONSUMED.toWindowInsets() } - override fun onTap(event: MotionEvent) { - when { - shouldShowControls -> showControls() - isTouchOnMedia(event) -> hideControls() - else -> restartHideControlsTimer() - } - } - - override fun showControls() { - super.showControls() - restartHideControlsTimer() - } - - override fun hideControls() { - super.hideControls() - cancelHideControlsTimer() - } - - private fun restartHideControlsTimer() { - hideControlsTimerJob?.cancel() - - if (activity.isInPictureInPictureMode) { - return - } - - hideControlsTimerJob = activity.lifecycleScope.launch { - delay(HIDE_CONTROLS_DELAY.milliseconds) - hideControls() - } - } - private fun cancelHideControlsTimer() { hideControlsTimerJob?.cancel() hideControlsTimerJob = null From 7abc363f90403b60711a02cfa8a1d782f570eb74 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Mon, 21 Sep 2026 16:52:30 +0200 Subject: [PATCH 4/6] use extension and remove unused extension Signed-off-by: alperozturk96 --- .../utils/extensions/ActionBarExtensions.kt | 19 ---------- .../utils/extensions/WindowExtensions.kt | 35 +++++++++++++++++++ .../ui/preview/PreviewImageActivity.kt | 13 +++---- .../ui/preview/PreviewImageFragment.kt | 2 +- .../ui/preview/PreviewPlaybackFragment.kt | 18 +++------- 5 files changed, 45 insertions(+), 42 deletions(-) delete mode 100644 app/src/main/java/com/nextcloud/utils/extensions/ActionBarExtensions.kt create mode 100644 app/src/main/java/com/nextcloud/utils/extensions/WindowExtensions.kt diff --git a/app/src/main/java/com/nextcloud/utils/extensions/ActionBarExtensions.kt b/app/src/main/java/com/nextcloud/utils/extensions/ActionBarExtensions.kt deleted file mode 100644 index 3bafc9b850e9..000000000000 --- a/app/src/main/java/com/nextcloud/utils/extensions/ActionBarExtensions.kt +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Nextcloud - Android Client - * - * SPDX-FileCopyrightText: 2024 Alper Ozturk - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -package com.nextcloud.utils.extensions - -import android.text.Spannable -import android.text.SpannableString -import android.text.style.ForegroundColorSpan -import androidx.appcompat.app.ActionBar - -fun ActionBar.setTitleColor(color: Int) { - val text = SpannableString(title ?: "") - text.setSpan(ForegroundColorSpan(color), 0, text.length, Spannable.SPAN_INCLUSIVE_INCLUSIVE) - title = text -} diff --git a/app/src/main/java/com/nextcloud/utils/extensions/WindowExtensions.kt b/app/src/main/java/com/nextcloud/utils/extensions/WindowExtensions.kt new file mode 100644 index 000000000000..966619e2f580 --- /dev/null +++ b/app/src/main/java/com/nextcloud/utils/extensions/WindowExtensions.kt @@ -0,0 +1,35 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2026 Alper Ozturk + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package com.nextcloud.utils.extensions + +import android.view.View +import android.view.Window +import androidx.appcompat.app.ActionBar +import androidx.core.view.WindowCompat +import androidx.core.view.WindowInsetsCompat +import androidx.core.view.WindowInsetsControllerCompat + +fun ActionBar.toggle(show: Boolean) { + if (show) { + show() + } else { + hide() + } +} + +fun Window.showSystemBar(show: Boolean, view: View) { + WindowCompat.getInsetsController(this, view).run { + val types = WindowInsetsCompat.Type.systemBars() + if (show) { + systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE + hide(types) + } else { + show(types) + } + } +} diff --git a/app/src/main/java/com/owncloud/android/ui/preview/PreviewImageActivity.kt b/app/src/main/java/com/owncloud/android/ui/preview/PreviewImageActivity.kt index 8d0a69ecdc4c..5049c8dfd5d3 100644 --- a/app/src/main/java/com/owncloud/android/ui/preview/PreviewImageActivity.kt +++ b/app/src/main/java/com/owncloud/android/ui/preview/PreviewImageActivity.kt @@ -44,6 +44,7 @@ import com.nextcloud.model.WorkerState import com.nextcloud.utils.extensions.getParcelableArgument import com.nextcloud.utils.extensions.getSerializableArgument import com.nextcloud.utils.extensions.observeWorker +import com.nextcloud.utils.extensions.toggle import com.owncloud.android.MainApp import com.owncloud.android.R import com.owncloud.android.datamodel.FileDataStorageManager @@ -195,12 +196,8 @@ class PreviewImageActivity : private fun displayCutOutSafeInsetTop(): Int = ViewCompat.getRootWindowInsets(window.decorView)?.displayCutout?.safeInsetTop ?: 0 - fun toggleActionBarVisibility(hide: Boolean) { - if (hide) { - supportActionBar?.hide() - } else { - supportActionBar?.show() - } + fun toggleActionBarVisibility(show: Boolean) { + supportActionBar?.toggle(show) } private fun initViewPager(user: User) { @@ -543,11 +540,11 @@ class PreviewImageActivity : if (isInPictureInPictureMode) { wasSystemUiVisibleBeforePictureInPicture = isSystemUIVisible - toggleActionBarVisibility(true) + toggleActionBarVisibility(false) return } - toggleActionBarVisibility(!wasSystemUiVisibleBeforePictureInPicture) + toggleActionBarVisibility(wasSystemUiVisibleBeforePictureInPicture) if (lifecycle.currentState != Lifecycle.State.CREATED) return diff --git a/app/src/main/java/com/owncloud/android/ui/preview/PreviewImageFragment.kt b/app/src/main/java/com/owncloud/android/ui/preview/PreviewImageFragment.kt index 587fdf35d586..25b5bebc386d 100644 --- a/app/src/main/java/com/owncloud/android/ui/preview/PreviewImageFragment.kt +++ b/app/src/main/java/com/owncloud/android/ui/preview/PreviewImageFragment.kt @@ -162,7 +162,7 @@ class PreviewImageFragment : private fun hideActionBar() { (requireActivity() as PreviewImageActivity).run { - toggleActionBarVisibility(true) + toggleActionBarVisibility(false) } } diff --git a/app/src/main/java/com/owncloud/android/ui/preview/PreviewPlaybackFragment.kt b/app/src/main/java/com/owncloud/android/ui/preview/PreviewPlaybackFragment.kt index 8134633f1835..5f3e4b5508ca 100644 --- a/app/src/main/java/com/owncloud/android/ui/preview/PreviewPlaybackFragment.kt +++ b/app/src/main/java/com/owncloud/android/ui/preview/PreviewPlaybackFragment.kt @@ -19,9 +19,6 @@ import androidx.activity.addCallback import androidx.core.content.ContextCompat import androidx.core.os.bundleOf import androidx.core.view.MenuProvider -import androidx.core.view.WindowCompat -import androidx.core.view.WindowInsetsCompat -import androidx.core.view.WindowInsetsControllerCompat import androidx.core.view.isVisible import androidx.fragment.app.Fragment import androidx.lifecycle.Lifecycle @@ -33,7 +30,6 @@ import com.nextcloud.client.player.media3.PlaybackModel import com.nextcloud.client.player.model.PlayerThumbnailLoader import com.nextcloud.client.player.model.file.PlaybackCollection import com.nextcloud.client.player.model.file.PlaybackFile -import com.nextcloud.client.player.util.PlayerUtil.toPlaybackFile import com.nextcloud.client.player.model.state.PlaybackState import com.nextcloud.client.player.model.state.VideoSize import com.nextcloud.client.player.ui.MediaNavigator @@ -41,11 +37,13 @@ import com.nextcloud.client.player.ui.PlayerLauncher import com.nextcloud.client.player.util.PlayerUtil.applyVideoSize import com.nextcloud.client.player.util.PlayerUtil.isPictureInPictureAllowed import com.nextcloud.client.player.util.PlayerUtil.ownsPlayback +import com.nextcloud.client.player.util.PlayerUtil.toPlaybackFile import com.nextcloud.ui.fileactions.FileAction import com.nextcloud.ui.fileactions.FileActionsBottomSheet import com.nextcloud.utils.extensions.getParcelableArgument import com.nextcloud.utils.extensions.getSerializableArgument import com.nextcloud.utils.extensions.setVisibilityWithAnimation +import com.nextcloud.utils.extensions.showSystemBar import com.owncloud.android.R import com.owncloud.android.databinding.PreviewPlaybackFragmentBinding import com.owncloud.android.datamodel.OCFile @@ -409,17 +407,9 @@ class PreviewPlaybackFragment : private fun toggleFullScreen() { val previewActivity = previewActivity() ?: return isFullScreen = !isFullScreen - - previewActivity.toggleActionBarVisibility(isFullScreen) + previewActivity.toggleActionBarVisibility(!isFullScreen) binding.playerControlView.setVisibilityWithAnimation(!isFullScreen) - - val insetsController = WindowCompat.getInsetsController(previewActivity.window, binding.root) - if (isFullScreen) { - insetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE - insetsController.hide(WindowInsetsCompat.Type.systemBars()) - } else { - insetsController.show(WindowInsetsCompat.Type.systemBars()) - } + previewActivity.window.showSystemBar(!isFullScreen, binding.root) } private fun updatePlayerControlsVisibility() { From 5adba20a08ca4f491aee6119c0676c94e8229023 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Mon, 21 Sep 2026 16:56:30 +0200 Subject: [PATCH 5/6] remove imports that not used Signed-off-by: alperozturk96 --- .../com/owncloud/android/ui/preview/PreviewImageFragment.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/ui/preview/PreviewImageFragment.kt b/app/src/main/java/com/owncloud/android/ui/preview/PreviewImageFragment.kt index 25b5bebc386d..5cbe74c00289 100644 --- a/app/src/main/java/com/owncloud/android/ui/preview/PreviewImageFragment.kt +++ b/app/src/main/java/com/owncloud/android/ui/preview/PreviewImageFragment.kt @@ -38,7 +38,6 @@ import androidx.core.content.res.ResourcesCompat import androidx.core.graphics.drawable.toDrawable import androidx.core.view.MenuHost import androidx.core.view.MenuProvider -import androidx.fragment.app.Fragment import androidx.lifecycle.Lifecycle import androidx.lifecycle.lifecycleScope import com.caverock.androidsvg.SVG @@ -49,6 +48,7 @@ import com.nextcloud.client.account.UserAccountManager import com.nextcloud.client.di.Injectable import com.nextcloud.client.jobs.BackgroundJobManager import com.nextcloud.client.network.ConnectivityService +import com.nextcloud.client.player.model.file.PlaybackCollection import com.nextcloud.ui.fileactions.FileAction import com.nextcloud.ui.fileactions.FileActionsBottomSheet.Companion.newInstance import com.nextcloud.utils.extensions.clickWithDebounce @@ -57,7 +57,6 @@ import com.nextcloud.utils.extensions.getParcelableArgument import com.nextcloud.utils.extensions.getSmallThumbnail import com.nextcloud.utils.extensions.typedActivity import com.owncloud.android.MainApp -import com.nextcloud.client.player.model.file.PlaybackCollection import com.owncloud.android.R import com.owncloud.android.databinding.PreviewImageFragmentBinding import com.owncloud.android.datamodel.OCFile From ce8184b47eb5b18982e0135747eb1d7fefe69d57 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Tue, 22 Sep 2026 12:02:21 +0200 Subject: [PATCH 6/6] hide nav bar as well Signed-off-by: alperozturk96 --- .../nextcloud/utils/extensions/WindowExtensions.kt | 14 +++++++++++++- .../android/ui/preview/PreviewPlaybackFragment.kt | 6 +++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/nextcloud/utils/extensions/WindowExtensions.kt b/app/src/main/java/com/nextcloud/utils/extensions/WindowExtensions.kt index 966619e2f580..4f9ba65373fd 100644 --- a/app/src/main/java/com/nextcloud/utils/extensions/WindowExtensions.kt +++ b/app/src/main/java/com/nextcloud/utils/extensions/WindowExtensions.kt @@ -26,10 +26,22 @@ fun Window.showSystemBar(show: Boolean, view: View) { WindowCompat.getInsetsController(this, view).run { val types = WindowInsetsCompat.Type.systemBars() if (show) { + show(types) + } else { systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE hide(types) - } else { + } + } +} + +fun Window.showNavigationBar(show: Boolean, view: View) { + WindowCompat.getInsetsController(this, view).run { + val types = WindowInsetsCompat.Type.navigationBars() + if (show) { show(types) + } else { + systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE + hide(types) } } } diff --git a/app/src/main/java/com/owncloud/android/ui/preview/PreviewPlaybackFragment.kt b/app/src/main/java/com/owncloud/android/ui/preview/PreviewPlaybackFragment.kt index 5f3e4b5508ca..893623cadfa6 100644 --- a/app/src/main/java/com/owncloud/android/ui/preview/PreviewPlaybackFragment.kt +++ b/app/src/main/java/com/owncloud/android/ui/preview/PreviewPlaybackFragment.kt @@ -43,6 +43,7 @@ import com.nextcloud.ui.fileactions.FileActionsBottomSheet import com.nextcloud.utils.extensions.getParcelableArgument import com.nextcloud.utils.extensions.getSerializableArgument import com.nextcloud.utils.extensions.setVisibilityWithAnimation +import com.nextcloud.utils.extensions.showNavigationBar import com.nextcloud.utils.extensions.showSystemBar import com.owncloud.android.R import com.owncloud.android.databinding.PreviewPlaybackFragmentBinding @@ -409,7 +410,10 @@ class PreviewPlaybackFragment : isFullScreen = !isFullScreen previewActivity.toggleActionBarVisibility(!isFullScreen) binding.playerControlView.setVisibilityWithAnimation(!isFullScreen) - previewActivity.window.showSystemBar(!isFullScreen, binding.root) + previewActivity.window.run { + showSystemBar(!isFullScreen, binding.root) + showNavigationBar(!isFullScreen, binding.root) + } } private fun updatePlayerControlsVisibility() {