Merge pull request #3373 from nextcloud/technicalDebt/#3372

Remove use of setSystemUiVisibility in previews #3372
This commit is contained in:
Marcel Hibbe 2023-10-11 14:54:49 +02:00 committed by GitHub
commit 3b4a9451f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 161 additions and 88 deletions

View File

@ -32,8 +32,15 @@ import android.util.Log
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import android.view.ViewGroup.MarginLayoutParams
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.FileProvider import androidx.core.content.FileProvider
import androidx.core.view.ViewCompat
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat
import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePadding
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import com.nextcloud.talk.BuildConfig import com.nextcloud.talk.BuildConfig
import com.nextcloud.talk.R import com.nextcloud.talk.R
@ -45,7 +52,7 @@ import java.io.File
class FullScreenImageActivity : AppCompatActivity() { class FullScreenImageActivity : AppCompatActivity() {
lateinit var binding: ActivityFullScreenImageBinding lateinit var binding: ActivityFullScreenImageBinding
private lateinit var windowInsetsController: WindowInsetsControllerCompat
private lateinit var path: String private lateinit var path: String
private var showFullscreen = false private var showFullscreen = false
@ -55,27 +62,31 @@ class FullScreenImageActivity : AppCompatActivity() {
} }
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
return if (item.itemId == android.R.id.home) { return when (item.itemId) {
onBackPressedDispatcher.onBackPressed() android.R.id.home -> {
true onBackPressedDispatcher.onBackPressed()
} else if (item.itemId == R.id.share) { true
val shareUri = FileProvider.getUriForFile(
this,
BuildConfig.APPLICATION_ID,
File(path)
)
val shareIntent: Intent = Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_STREAM, shareUri)
type = IMAGE_PREFIX_GENERIC
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
} }
startActivity(Intent.createChooser(shareIntent, resources.getText(R.string.send_to))) R.id.share -> {
val shareUri = FileProvider.getUriForFile(
this,
BuildConfig.APPLICATION_ID,
File(path)
)
true val shareIntent: Intent = Intent().apply {
} else { action = Intent.ACTION_SEND
super.onOptionsItemSelected(item) putExtra(Intent.EXTRA_STREAM, shareUri)
type = IMAGE_PREFIX_GENERIC
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
startActivity(Intent.createChooser(shareIntent, resources.getText(R.string.send_to)))
true
}
else -> {
super.onOptionsItemSelected(item)
}
} }
} }
@ -86,8 +97,10 @@ class FullScreenImageActivity : AppCompatActivity() {
setContentView(binding.root) setContentView(binding.root)
setSupportActionBar(binding.imageviewToolbar) setSupportActionBar(binding.imageviewToolbar)
WindowCompat.setDecorFitsSystemWindows(window, false)
binding.photoView.setOnPhotoTapListener { view, x, y -> initWindowInsetsController()
applyWindowInsets()
binding.photoView.setOnPhotoTapListener { _, _, _ ->
toggleFullscreen() toggleFullscreen()
} }
binding.photoView.setOnOutsidePhotoTapListener { binding.photoView.setOnOutsidePhotoTapListener {
@ -142,35 +155,41 @@ class FullScreenImageActivity : AppCompatActivity() {
private fun toggleFullscreen() { private fun toggleFullscreen() {
showFullscreen = !showFullscreen showFullscreen = !showFullscreen
if (showFullscreen) { if (showFullscreen) {
hideSystemUI() enterImmersiveMode()
supportActionBar?.hide()
} else { } else {
showSystemUI() exitImmersiveMode()
supportActionBar?.show()
} }
} }
private fun hideSystemUI() { private fun initWindowInsetsController() {
window.decorView.systemUiVisibility = ( windowInsetsController = WindowCompat.getInsetsController(window, window.decorView)
View.SYSTEM_UI_FLAG_IMMERSIVE windowInsetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_FULLSCREEN
)
} }
private fun showSystemUI() { private fun enterImmersiveMode() {
window.decorView.systemUiVisibility = ( windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
View.SYSTEM_UI_FLAG_LAYOUT_STABLE supportActionBar?.hide()
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION }
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
) private fun exitImmersiveMode() {
windowInsetsController.show(WindowInsetsCompat.Type.systemBars())
supportActionBar?.show()
}
private fun applyWindowInsets() {
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { _, windowInsets ->
val insets =
windowInsets.getInsets(WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout())
binding.imageviewToolbar.updateLayoutParams<MarginLayoutParams> {
topMargin = insets.top
}
binding.imageviewToolbar.updatePadding(left = insets.left, right = insets.right)
WindowInsetsCompat.CONSUMED
}
} }
companion object { companion object {
private val TAG = "FullScreenImageActivity" private const val TAG = "FullScreenImageActivity"
private const val HUNDRED_MB = 100 * 1024 * 1024 private const val HUNDRED_MB = 100 * 1024 * 1024
private const val MAX_SCALE = 6.0f private const val MAX_SCALE = 6.0f
private const val MEDIUM_SCALE = 2.45f private const val MEDIUM_SCALE = 2.45f

View File

@ -30,14 +30,23 @@ import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.ViewGroup.MarginLayoutParams
import android.view.WindowManager import android.view.WindowManager
import android.widget.FrameLayout
import androidx.annotation.OptIn import androidx.annotation.OptIn
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.FileProvider import androidx.core.content.FileProvider
import androidx.core.view.ViewCompat
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat
import androidx.core.view.marginBottom
import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePadding
import androidx.media3.common.MediaItem import androidx.media3.common.MediaItem
import androidx.media3.common.util.UnstableApi import androidx.media3.common.util.UnstableApi
import androidx.media3.exoplayer.ExoPlayer import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.ui.DefaultTimeBar
import androidx.media3.ui.PlayerView import androidx.media3.ui.PlayerView
import autodagger.AutoInjector import autodagger.AutoInjector
import com.nextcloud.talk.BuildConfig import com.nextcloud.talk.BuildConfig
@ -56,6 +65,7 @@ class FullScreenMediaActivity : AppCompatActivity() {
private var playWhenReadyState: Boolean = true private var playWhenReadyState: Boolean = true
private var playBackPosition: Long = 0L private var playBackPosition: Long = 0L
private lateinit var windowInsetsController: WindowInsetsControllerCompat
override fun onCreateOptionsMenu(menu: Menu): Boolean { override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu_preview, menu) menuInflater.inflate(R.menu.menu_preview, menu)
@ -63,34 +73,38 @@ class FullScreenMediaActivity : AppCompatActivity() {
} }
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
return if (item.itemId == android.R.id.home) { return when (item.itemId) {
onBackPressedDispatcher.onBackPressed() android.R.id.home -> {
true onBackPressedDispatcher.onBackPressed()
} else if (item.itemId == R.id.share) { true
val shareUri = FileProvider.getUriForFile(
this,
BuildConfig.APPLICATION_ID,
File(path)
)
val shareIntent: Intent = Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_STREAM, shareUri)
type = VIDEO_PREFIX_GENERIC
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
} }
startActivity(Intent.createChooser(shareIntent, resources.getText(R.string.send_to))) R.id.share -> {
val shareUri = FileProvider.getUriForFile(
this,
BuildConfig.APPLICATION_ID,
File(path)
)
true val shareIntent: Intent = Intent().apply {
} else { action = Intent.ACTION_SEND
super.onOptionsItemSelected(item) putExtra(Intent.EXTRA_STREAM, shareUri)
type = VIDEO_PREFIX_GENERIC
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
startActivity(Intent.createChooser(shareIntent, resources.getText(R.string.send_to)))
true
}
else -> {
super.onOptionsItemSelected(item)
}
} }
} }
@OptIn(UnstableApi::class) @OptIn(UnstableApi::class)
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
WindowCompat.setDecorFitsSystemWindows(window, false)
val fileName = intent.getStringExtra("FILE_NAME") val fileName = intent.getStringExtra("FILE_NAME")
val isAudioOnly = intent.getBooleanExtra("AUDIO_ONLY", false) val isAudioOnly = intent.getBooleanExtra("AUDIO_ONLY", false)
@ -110,14 +124,15 @@ class FullScreenMediaActivity : AppCompatActivity() {
binding.playerView.controllerShowTimeoutMs = 0 binding.playerView.controllerShowTimeoutMs = 0
} }
initWindowInsetsController()
applyWindowInsets()
binding.playerView.setControllerVisibilityListener( binding.playerView.setControllerVisibilityListener(
PlayerView.ControllerVisibilityListener { v -> PlayerView.ControllerVisibilityListener { v ->
if (v != 0) { if (v != 0) {
hideSystemUI() enterImmersiveMode()
supportActionBar?.hide()
} else { } else {
showSystemUI() exitImmersiveMode()
supportActionBar?.show()
} }
} }
) )
@ -158,22 +173,44 @@ class FullScreenMediaActivity : AppCompatActivity() {
player = null player = null
} }
private fun hideSystemUI() { private fun initWindowInsetsController() {
window.decorView.systemUiVisibility = ( windowInsetsController = WindowCompat.getInsetsController(window, window.decorView)
View.SYSTEM_UI_FLAG_IMMERSIVE windowInsetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_FULLSCREEN
)
} }
private fun showSystemUI() { private fun enterImmersiveMode() {
window.decorView.systemUiVisibility = ( windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
View.SYSTEM_UI_FLAG_LAYOUT_STABLE supportActionBar?.hide()
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION }
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
private fun exitImmersiveMode() {
windowInsetsController.show(WindowInsetsCompat.Type.systemBars())
supportActionBar?.show()
}
private fun applyWindowInsets() {
val playerView = binding.playerView
val exoControls = playerView.findViewById<FrameLayout>(R.id.exo_bottom_bar)
val exoProgress = playerView.findViewById<DefaultTimeBar>(R.id.exo_progress)
val progressBottomMargin = exoProgress.marginBottom
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { _, windowInsets ->
val insets = windowInsets.getInsets(
WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type
.displayCutout()
) )
binding.mediaviewToolbar.updateLayoutParams<MarginLayoutParams> {
topMargin = insets.top
}
exoControls.updateLayoutParams<MarginLayoutParams> {
bottomMargin = insets.bottom
}
exoProgress.updateLayoutParams<MarginLayoutParams> {
bottomMargin = insets.bottom + progressBottomMargin
}
exoControls.updatePadding(left = insets.left, right = insets.right)
exoProgress.updatePadding(left = insets.left, right = insets.right)
binding.mediaviewToolbar.updatePadding(left = insets.left, right = insets.right)
WindowInsetsCompat.CONSUMED
}
} }
} }

View File

@ -28,7 +28,6 @@
android:id="@+id/image_wrapper_view" android:id="@+id/image_wrapper_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".activities.FullScreenImageActivity"> tools:context=".activities.FullScreenImageActivity">
<com.google.android.material.appbar.MaterialToolbar <com.google.android.material.appbar.MaterialToolbar

View File

@ -25,7 +25,6 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".activities.FullScreenMediaActivity"> tools:context=".activities.FullScreenMediaActivity">
<androidx.appcompat.widget.Toolbar <androidx.appcompat.widget.Toolbar

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="FullScreenImageTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">@color/black</item>
<item name="android:navigationBarColor">@color/transparent</item>
<item name="android:statusBarColor">@color/transparent</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowActionBar">true</item>
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
</style>
<style name="FullScreenMediaTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">@color/black</item>
<item name="android:navigationBarColor">@color/black</item>
<item name="android:statusBarColor">@color/transparent</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowActionBar">true</item>
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
</style>
</resources>

View File

@ -217,20 +217,18 @@
<style name="FullScreenImageTheme" parent="Theme.AppCompat.Light.NoActionBar"> <style name="FullScreenImageTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">@color/black</item> <item name="android:windowBackground">@color/black</item>
<item name="android:navigationBarColor">@color/black</item> <item name="android:navigationBarColor">@color/transparent</item>
<item name="android:statusBarColor">@color/transparent</item>
<item name="android:windowNoTitle">true</item> <item name="android:windowNoTitle">true</item>
<item name="android:windowActionBar">true</item> <item name="android:windowActionBar">true</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowContentOverlay">@null</item>
</style> </style>
<style name="FullScreenMediaTheme" parent="Theme.AppCompat.Light.NoActionBar"> <style name="FullScreenMediaTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">@color/black</item> <item name="android:windowBackground">@color/black</item>
<item name="android:navigationBarColor">@color/black</item> <item name="android:navigationBarColor">@color/black</item>
<item name="android:statusBarColor">@color/transparent</item>
<item name="android:windowNoTitle">true</item> <item name="android:windowNoTitle">true</item>
<item name="android:windowActionBar">true</item> <item name="android:windowActionBar">true</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowContentOverlay">@null</item>
</style> </style>
<style name="TextInputLayoutTheme" parent="Theme.AppCompat"> <style name="TextInputLayoutTheme" parent="Theme.AppCompat">