mirror of
https://github.com/libre-tube/LibreTube.git
synced 2024-12-14 14:20:30 +05:30
Merge pull request #4981 from Bnyro/landscape-player-page
feat: landscape layout for player page
This commit is contained in:
commit
fc9e3e6501
@ -1,15 +1,14 @@
|
|||||||
package com.github.libretube.helpers
|
package com.github.libretube.helpers
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import android.view.Window
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import androidx.core.view.WindowCompat
|
import androidx.core.view.WindowCompat
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
import com.github.libretube.ui.extensions.toggleSystemBars
|
import com.github.libretube.ui.extensions.toggleSystemBars
|
||||||
|
|
||||||
object WindowHelper {
|
object WindowHelper {
|
||||||
fun toggleFullscreen(activity: Activity, isFullscreen: Boolean) {
|
fun toggleFullscreen(window: Window, isFullscreen: Boolean) {
|
||||||
val window = activity.window
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||||
window.attributes.layoutInDisplayCutoutMode = if (isFullscreen) {
|
window.attributes.layoutInDisplayCutoutMode = if (isFullscreen) {
|
||||||
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
|
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
|
||||||
@ -30,7 +29,7 @@ object WindowHelper {
|
|||||||
// Show the system bars when it is not fullscreen and hide them when it is fullscreen
|
// Show the system bars when it is not fullscreen and hide them when it is fullscreen
|
||||||
// System bars means status bar and the navigation bar
|
// System bars means status bar and the navigation bar
|
||||||
// See: https://developer.android.com/training/system-ui/immersive#kotlin
|
// See: https://developer.android.com/training/system-ui/immersive#kotlin
|
||||||
activity.toggleSystemBars(
|
window.toggleSystemBars(
|
||||||
types = WindowInsetsCompat.Type.systemBars(),
|
types = WindowInsetsCompat.Type.systemBars(),
|
||||||
showBars = !isFullscreen
|
showBars = !isFullscreen
|
||||||
)
|
)
|
||||||
|
@ -486,8 +486,8 @@ class MainActivity : BaseActivity() {
|
|||||||
super.onConfigurationChanged(newConfig)
|
super.onConfigurationChanged(newConfig)
|
||||||
|
|
||||||
when (newConfig.orientation) {
|
when (newConfig.orientation) {
|
||||||
Configuration.ORIENTATION_PORTRAIT -> WindowHelper.toggleFullscreen(this, false)
|
Configuration.ORIENTATION_PORTRAIT -> WindowHelper.toggleFullscreen(window, false)
|
||||||
Configuration.ORIENTATION_LANDSCAPE -> WindowHelper.toggleFullscreen(this, true)
|
Configuration.ORIENTATION_LANDSCAPE -> WindowHelper.toggleFullscreen(window, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ class OfflinePlayerActivity : BaseActivity() {
|
|||||||
private val playerViewModel: PlayerViewModel by viewModels()
|
private val playerViewModel: PlayerViewModel by viewModels()
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
WindowHelper.toggleFullscreen(this, true)
|
WindowHelper.toggleFullscreen(window, true)
|
||||||
|
|
||||||
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
|
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ import com.github.libretube.helpers.ThemeHelper
|
|||||||
* Activity that applies the LibreTube theme and the in-app language
|
* Activity that applies the LibreTube theme and the in-app language
|
||||||
*/
|
*/
|
||||||
open class BaseActivity : AppCompatActivity() {
|
open class BaseActivity : AppCompatActivity() {
|
||||||
private val screenOrientationPref by lazy {
|
val screenOrientationPref by lazy {
|
||||||
val orientationPref = PreferenceHelper.getString(
|
val orientationPref = PreferenceHelper.getString(
|
||||||
PreferenceKeys.ORIENTATION,
|
PreferenceKeys.ORIENTATION,
|
||||||
resources.getString(R.string.config_default_orientation_pref)
|
resources.getString(R.string.config_default_orientation_pref)
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
package com.github.libretube.ui.extensions
|
package com.github.libretube.ui.extensions
|
||||||
|
|
||||||
import android.app.Activity
|
import android.view.Window
|
||||||
import androidx.core.view.WindowCompat
|
import androidx.core.view.WindowCompat
|
||||||
import androidx.core.view.WindowInsetsCompat.Type.InsetsType
|
import androidx.core.view.WindowInsetsCompat.Type.InsetsType
|
||||||
import androidx.core.view.WindowInsetsControllerCompat
|
import androidx.core.view.WindowInsetsControllerCompat
|
||||||
|
|
||||||
fun Activity.toggleSystemBars(@InsetsType types: Int, showBars: Boolean) {
|
fun Window.toggleSystemBars(@InsetsType types: Int, showBars: Boolean) {
|
||||||
WindowCompat.getInsetsController(window, window.decorView).apply {
|
WindowCompat.getInsetsController(this, decorView).apply {
|
||||||
systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
||||||
if (showBars) {
|
if (showBars) {
|
||||||
show(types)
|
show(types)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.github.libretube.ui.fragments
|
package com.github.libretube.ui.fragments
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
import android.app.Dialog
|
||||||
import android.content.BroadcastReceiver
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
@ -17,7 +18,9 @@ import android.text.format.DateUtils
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.view.ViewGroup.LayoutParams
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import android.window.OnBackInvokedDispatcher
|
||||||
import androidx.constraintlayout.motion.widget.MotionLayout
|
import androidx.constraintlayout.motion.widget.MotionLayout
|
||||||
import androidx.constraintlayout.motion.widget.TransitionAdapter
|
import androidx.constraintlayout.motion.widget.TransitionAdapter
|
||||||
import androidx.core.content.getSystemService
|
import androidx.core.content.getSystemService
|
||||||
@ -85,12 +88,14 @@ import com.github.libretube.helpers.PlayerHelper.getVideoStats
|
|||||||
import com.github.libretube.helpers.PlayerHelper.isInSegment
|
import com.github.libretube.helpers.PlayerHelper.isInSegment
|
||||||
import com.github.libretube.helpers.PreferenceHelper
|
import com.github.libretube.helpers.PreferenceHelper
|
||||||
import com.github.libretube.helpers.ProxyHelper
|
import com.github.libretube.helpers.ProxyHelper
|
||||||
|
import com.github.libretube.helpers.WindowHelper
|
||||||
import com.github.libretube.obj.PlayerNotificationData
|
import com.github.libretube.obj.PlayerNotificationData
|
||||||
import com.github.libretube.obj.ShareData
|
import com.github.libretube.obj.ShareData
|
||||||
import com.github.libretube.obj.VideoResolution
|
import com.github.libretube.obj.VideoResolution
|
||||||
import com.github.libretube.parcelable.PlayerData
|
import com.github.libretube.parcelable.PlayerData
|
||||||
import com.github.libretube.ui.activities.MainActivity
|
import com.github.libretube.ui.activities.MainActivity
|
||||||
import com.github.libretube.ui.adapters.VideosAdapter
|
import com.github.libretube.ui.adapters.VideosAdapter
|
||||||
|
import com.github.libretube.ui.base.BaseActivity
|
||||||
import com.github.libretube.ui.dialogs.AddToPlaylistDialog
|
import com.github.libretube.ui.dialogs.AddToPlaylistDialog
|
||||||
import com.github.libretube.ui.dialogs.DownloadDialog
|
import com.github.libretube.ui.dialogs.DownloadDialog
|
||||||
import com.github.libretube.ui.dialogs.ShareDialog
|
import com.github.libretube.ui.dialogs.ShareDialog
|
||||||
@ -188,6 +193,21 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
|||||||
private var scrubbingTimeBar = false
|
private var scrubbingTimeBar = false
|
||||||
private var chaptersBottomSheet: ChaptersBottomSheet? = null
|
private var chaptersBottomSheet: ChaptersBottomSheet? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The orientation of the `fragment_player.xml` that's currently used
|
||||||
|
* This is needed in order to figure out if the current layout is the landscape one or not.
|
||||||
|
*/
|
||||||
|
private var playerLayoutOrientation = Int.MIN_VALUE
|
||||||
|
|
||||||
|
private val fullscreenDialog by lazy {
|
||||||
|
object: Dialog(requireContext(), android.R.style.Theme_Black_NoTitleBar_Fullscreen) {
|
||||||
|
override fun onBackPressed() {
|
||||||
|
super.onBackPressed()
|
||||||
|
unsetFullscreen()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Receiver for all actions in the PiP mode
|
* Receiver for all actions in the PiP mode
|
||||||
*/
|
*/
|
||||||
@ -236,6 +256,8 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
|||||||
keepQueue = playerData.keepQueue
|
keepQueue = playerData.keepQueue
|
||||||
timeStamp = playerData.timestamp
|
timeStamp = playerData.timestamp
|
||||||
|
|
||||||
|
playerLayoutOrientation = resources.configuration.orientation
|
||||||
|
|
||||||
// broadcast receiver for PiP actions
|
// broadcast receiver for PiP actions
|
||||||
context?.registerReceiver(
|
context?.registerReceiver(
|
||||||
broadcastReceiver,
|
broadcastReceiver,
|
||||||
@ -365,17 +387,19 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
|||||||
.isPictureInPictureAvailable(activity)
|
.isPictureInPictureAvailable(activity)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun onManualPlayerClose() {
|
||||||
|
PlayingQueue.clear()
|
||||||
|
BackgroundHelper.stopBackgroundPlay(requireContext())
|
||||||
|
killPlayerFragment()
|
||||||
|
}
|
||||||
|
|
||||||
// actions that don't depend on video information
|
// actions that don't depend on video information
|
||||||
private fun initializeOnClickActions() {
|
private fun initializeOnClickActions() {
|
||||||
binding.closeImageView.setOnClickListener {
|
binding.closeImageView.setOnClickListener {
|
||||||
PlayingQueue.clear()
|
onManualPlayerClose()
|
||||||
BackgroundHelper.stopBackgroundPlay(requireContext())
|
|
||||||
killPlayerFragment()
|
|
||||||
}
|
}
|
||||||
playerBinding.closeImageButton.setOnClickListener {
|
playerBinding.closeImageButton.setOnClickListener {
|
||||||
PlayingQueue.clear()
|
onManualPlayerClose()
|
||||||
BackgroundHelper.stopBackgroundPlay(requireContext())
|
|
||||||
killPlayerFragment()
|
|
||||||
}
|
}
|
||||||
playerBinding.autoPlay.isVisible = true
|
playerBinding.autoPlay.isVisible = true
|
||||||
|
|
||||||
@ -499,50 +523,30 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
|||||||
NavigationHelper.startAudioPlayer(requireContext())
|
NavigationHelper.startAudioPlayer(requireContext())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* If enabled, determine the orientation o use based on the video's aspect ratio
|
|
||||||
* Expected behavior: Portrait for shorts, Landscape for normal videos
|
|
||||||
*/
|
|
||||||
private fun updateFullscreenOrientation() {
|
|
||||||
if (!PlayerHelper.autoFullscreenEnabled) {
|
|
||||||
val height = streams.videoStreams.firstOrNull()?.height ?: exoPlayer.videoSize.height
|
|
||||||
val width = streams.videoStreams.firstOrNull()?.width ?: exoPlayer.videoSize.width
|
|
||||||
|
|
||||||
// different orientations of the video are only available when autorotation is disabled
|
|
||||||
val orientation = PlayerHelper.getOrientation(width, height)
|
|
||||||
mainActivity.requestedOrientation = orientation
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setFullscreen() {
|
private fun setFullscreen() {
|
||||||
with(binding.playerMotionLayout) {
|
|
||||||
getConstraintSet(R.id.start).constrainHeight(R.id.player, -1)
|
|
||||||
enableTransition(R.id.yt_transition, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
// set status bar icon color to white
|
// set status bar icon color to white
|
||||||
windowInsetsControllerCompat.isAppearanceLightStatusBars = false
|
windowInsetsControllerCompat.isAppearanceLightStatusBars = false
|
||||||
|
|
||||||
binding.mainContainer.isClickable = true
|
viewModel.isFullscreen.value = true
|
||||||
binding.linLayout.isGone = true
|
|
||||||
|
if (mainActivity.screenOrientationPref == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT) {
|
||||||
|
val height = streams.videoStreams.firstOrNull()?.height ?: exoPlayer.videoSize.height
|
||||||
|
val width = streams.videoStreams.firstOrNull()?.width ?: exoPlayer.videoSize.width
|
||||||
|
|
||||||
|
mainActivity.requestedOrientation = PlayerHelper.getOrientation(width, height)
|
||||||
|
}
|
||||||
|
|
||||||
commentsViewModel.setCommentSheetExpand(null)
|
commentsViewModel.setCommentSheetExpand(null)
|
||||||
playerBinding.fullscreen.setImageResource(R.drawable.ic_fullscreen_exit)
|
playerBinding.fullscreen.setImageResource(R.drawable.ic_fullscreen_exit)
|
||||||
playerBinding.exoTitle.isVisible = true
|
playerBinding.exoTitle.isVisible = true
|
||||||
|
|
||||||
updateFullscreenOrientation()
|
|
||||||
viewModel.isFullscreen.value = true
|
|
||||||
|
|
||||||
updateResolutionOnFullscreenChange(true)
|
updateResolutionOnFullscreenChange(true)
|
||||||
|
|
||||||
|
openOrCloseFullscreenDialog(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("SourceLockedOrientationActivity")
|
@SuppressLint("SourceLockedOrientationActivity")
|
||||||
fun unsetFullscreen() {
|
fun unsetFullscreen() {
|
||||||
// leave fullscreen mode
|
|
||||||
with(binding.playerMotionLayout) {
|
|
||||||
getConstraintSet(R.id.start).constrainHeight(R.id.player, 0)
|
|
||||||
enableTransition(R.id.yt_transition, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
// set status bar icon color back to theme color
|
// set status bar icon color back to theme color
|
||||||
windowInsetsControllerCompat.isAppearanceLightStatusBars =
|
windowInsetsControllerCompat.isAppearanceLightStatusBars =
|
||||||
when (resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) {
|
when (resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) {
|
||||||
@ -551,19 +555,40 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
|||||||
else -> true
|
else -> true
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.mainContainer.isClickable = false
|
viewModel.isFullscreen.value = false
|
||||||
binding.linLayout.isVisible = true
|
|
||||||
playerBinding.fullscreen.setImageResource(R.drawable.ic_fullscreen)
|
|
||||||
playerBinding.exoTitle.isInvisible = true
|
|
||||||
|
|
||||||
if (!PlayerHelper.autoFullscreenEnabled) {
|
if (mainActivity.screenOrientationPref == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT) {
|
||||||
// switch back to portrait mode if autorotation disabled
|
|
||||||
mainActivity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
|
mainActivity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.isFullscreen.value = false
|
playerBinding.fullscreen.setImageResource(R.drawable.ic_fullscreen)
|
||||||
|
playerBinding.exoTitle.isInvisible = true
|
||||||
|
|
||||||
updateResolutionOnFullscreenChange(false)
|
updateResolutionOnFullscreenChange(false)
|
||||||
|
|
||||||
|
openOrCloseFullscreenDialog(false)
|
||||||
|
|
||||||
|
checkForNecessaryOrientationRestart()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun openOrCloseFullscreenDialog(open: Boolean) {
|
||||||
|
val playerView = binding.player
|
||||||
|
(playerView.parent as ViewGroup).removeView(playerView)
|
||||||
|
|
||||||
|
if (open) {
|
||||||
|
fullscreenDialog.addContentView(
|
||||||
|
binding.player,
|
||||||
|
LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
|
||||||
|
)
|
||||||
|
fullscreenDialog.show()
|
||||||
|
playerView.currentWindow = fullscreenDialog.window
|
||||||
|
} else {
|
||||||
|
binding.playerMotionLayout.addView(playerView)
|
||||||
|
playerView.currentWindow = null
|
||||||
|
fullscreenDialog.dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowHelper.toggleFullscreen(fullscreenDialog.window!!, open)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
@ -735,8 +760,6 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
|||||||
initializePlayerView()
|
initializePlayerView()
|
||||||
setupSeekbarPreview()
|
setupSeekbarPreview()
|
||||||
|
|
||||||
if (viewModel.isFullscreen.value == true) updateFullscreenOrientation()
|
|
||||||
|
|
||||||
exoPlayer.playWhenReady = PlayerHelper.playAutomatically
|
exoPlayer.playWhenReady = PlayerHelper.playAutomatically
|
||||||
exoPlayer.prepare()
|
exoPlayer.prepare()
|
||||||
|
|
||||||
@ -1341,7 +1364,7 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
|||||||
onConfigurationChanged(resources.configuration)
|
onConfigurationChanged(resources.configuration)
|
||||||
} else {
|
} else {
|
||||||
// go to portrait mode
|
// go to portrait mode
|
||||||
mainActivity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
|
mainActivity.requestedOrientation = (requireActivity() as BaseActivity).screenOrientationPref
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1470,13 +1493,9 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
|||||||
viewModel.isMiniPlayerVisible.value = false
|
viewModel.isMiniPlayerVisible.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
with(binding.playerMotionLayout) {
|
|
||||||
getConstraintSet(R.id.start).constrainHeight(R.id.player, -1)
|
|
||||||
enableTransition(R.id.yt_transition, false)
|
|
||||||
}
|
|
||||||
binding.linLayout.isGone = true
|
|
||||||
|
|
||||||
updateCurrentSubtitle(null)
|
updateCurrentSubtitle(null)
|
||||||
|
|
||||||
|
openOrCloseFullscreenDialog(true)
|
||||||
} else {
|
} else {
|
||||||
// close button got clicked in PiP mode
|
// close button got clicked in PiP mode
|
||||||
// pause the video and keep the app alive
|
// pause the video and keep the app alive
|
||||||
@ -1485,20 +1504,13 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
|||||||
// enable exoPlayer controls again
|
// enable exoPlayer controls again
|
||||||
binding.player.useController = true
|
binding.player.useController = true
|
||||||
|
|
||||||
// set back to portrait mode
|
|
||||||
if (viewModel.isFullscreen.value != true) {
|
|
||||||
with(binding.playerMotionLayout) {
|
|
||||||
getConstraintSet(R.id.start).constrainHeight(R.id.player, 0)
|
|
||||||
enableTransition(R.id.yt_transition, true)
|
|
||||||
}
|
|
||||||
binding.linLayout.isVisible = true
|
|
||||||
}
|
|
||||||
|
|
||||||
updateCurrentSubtitle(currentSubtitle)
|
updateCurrentSubtitle(currentSubtitle)
|
||||||
|
|
||||||
binding.optionsLL.post {
|
binding.optionsLL.post {
|
||||||
binding.optionsLL.requestLayout()
|
binding.optionsLL.requestLayout()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
openOrCloseFullscreenDialog(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1564,6 +1576,12 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
|||||||
private fun killPlayerFragment() {
|
private fun killPlayerFragment() {
|
||||||
viewModel.isFullscreen.value = false
|
viewModel.isFullscreen.value = false
|
||||||
viewModel.isMiniPlayerVisible.value = false
|
viewModel.isMiniPlayerVisible.value = false
|
||||||
|
|
||||||
|
// dismiss the fullscreen dialog if it's currently visible
|
||||||
|
// otherwise it would stay alive while being detached from this fragment
|
||||||
|
fullscreenDialog.dismiss()
|
||||||
|
binding.player.currentWindow = null
|
||||||
|
|
||||||
binding.playerMotionLayout.transitionToEnd()
|
binding.playerMotionLayout.transitionToEnd()
|
||||||
mainActivity.supportFragmentManager.commit {
|
mainActivity.supportFragmentManager.commit {
|
||||||
remove(this@PlayerFragment)
|
remove(this@PlayerFragment)
|
||||||
@ -1572,21 +1590,43 @@ class PlayerFragment : Fragment(), OnlinePlayerOptions {
|
|||||||
onDestroy()
|
onDestroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the activity needs to be recreated due to an orientation change
|
||||||
|
* If true, the activity will be automatically restarted
|
||||||
|
*/
|
||||||
|
private fun checkForNecessaryOrientationRestart() {
|
||||||
|
val lockedOrientations = listOf(ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT, ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
|
||||||
|
if (mainActivity.screenOrientationPref in lockedOrientations) return
|
||||||
|
|
||||||
|
val orientation = resources.configuration.orientation
|
||||||
|
if (viewModel.isFullscreen.value != true && orientation != playerLayoutOrientation) {
|
||||||
|
if (this::exoPlayer.isInitialized) {
|
||||||
|
arguments?.putLong(IntentData.timeStamp, exoPlayer.currentPosition / 1000)
|
||||||
|
}
|
||||||
|
playerLayoutOrientation = orientation
|
||||||
|
activity?.recreate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||||
super.onConfigurationChanged(newConfig)
|
super.onConfigurationChanged(newConfig)
|
||||||
|
|
||||||
if (!PlayerHelper.autoFullscreenEnabled || _binding == null ||
|
if (_binding == null ||
|
||||||
// If in PiP mode, orientation is given as landscape.
|
// If in PiP mode, orientation is given as landscape.
|
||||||
PictureInPictureCompat.isInPictureInPictureMode(requireActivity())
|
PictureInPictureCompat.isInPictureInPictureMode(requireActivity())
|
||||||
) {
|
) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
when (newConfig.orientation) {
|
if (PlayerHelper.autoFullscreenEnabled) {
|
||||||
// go to fullscreen mode
|
when (newConfig.orientation) {
|
||||||
Configuration.ORIENTATION_LANDSCAPE -> setFullscreen()
|
// go to fullscreen mode
|
||||||
// exit fullscreen if not landscape
|
Configuration.ORIENTATION_LANDSCAPE -> setFullscreen()
|
||||||
else -> unsetFullscreen()
|
// exit fullscreen if not landscape
|
||||||
|
else -> unsetFullscreen()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
checkForNecessaryOrientationRestart()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,19 +39,6 @@ class CommentsSheet : UndimmedBottomSheet() {
|
|||||||
|
|
||||||
val binding = binding
|
val binding = binding
|
||||||
|
|
||||||
binding.dragHandle.viewTreeObserver.addOnGlobalLayoutListener(object :
|
|
||||||
ViewTreeObserver.OnGlobalLayoutListener {
|
|
||||||
override fun onGlobalLayout() {
|
|
||||||
binding.dragHandle.viewTreeObserver.removeOnGlobalLayoutListener(this)
|
|
||||||
|
|
||||||
// limit the recyclerview height to not cover the video
|
|
||||||
binding.standardBottomSheet.layoutParams =
|
|
||||||
binding.commentFragContainer.layoutParams.apply {
|
|
||||||
height = playerViewModel.maxSheetHeightPx
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
binding.btnBack.setOnClickListener {
|
binding.btnBack.setOnClickListener {
|
||||||
if (childFragmentManager.backStackEntryCount > 0) {
|
if (childFragmentManager.backStackEntryCount > 0) {
|
||||||
childFragmentManager.popBackStack()
|
childFragmentManager.popBackStack()
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.github.libretube.ui.sheets
|
package com.github.libretube.ui.sheets
|
||||||
|
|
||||||
import android.app.Dialog
|
import android.app.Dialog
|
||||||
|
import android.content.res.Configuration
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.KeyEvent
|
import android.view.KeyEvent
|
||||||
import android.view.View
|
import android.view.View
|
||||||
@ -21,9 +22,11 @@ abstract class UndimmedBottomSheet : ExpandedBottomSheet() {
|
|||||||
override fun onGlobalLayout() {
|
override fun onGlobalLayout() {
|
||||||
getDragHandle().viewTreeObserver.removeOnGlobalLayoutListener(this)
|
getDragHandle().viewTreeObserver.removeOnGlobalLayoutListener(this)
|
||||||
|
|
||||||
// limit the recyclerview height to not cover the video
|
if (resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) {
|
||||||
getBottomSheet().updateLayoutParams {
|
// limit the recyclerview height to not cover the video
|
||||||
height = getSheetMaxHeightPx()
|
getBottomSheet().updateLayoutParams {
|
||||||
|
height = getSheetMaxHeightPx()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -11,6 +11,7 @@ import android.text.format.DateUtils
|
|||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.view.Window
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
@ -87,6 +88,12 @@ open class CustomExoPlayerView(
|
|||||||
updateCurrentPosition()
|
updateCurrentPosition()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The window that needs to be addressed for showing and hiding the system bars
|
||||||
|
* If null, the activity's default/main window will be used
|
||||||
|
*/
|
||||||
|
var currentWindow: Window? = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Preferences
|
* Preferences
|
||||||
*/
|
*/
|
||||||
@ -143,7 +150,7 @@ open class CustomExoPlayerView(
|
|||||||
// change locked status
|
// change locked status
|
||||||
isPlayerLocked = !isPlayerLocked
|
isPlayerLocked = !isPlayerLocked
|
||||||
|
|
||||||
activity.toggleSystemBars(
|
(currentWindow ?: activity.window).toggleSystemBars(
|
||||||
types = WindowInsetsCompat.Type.statusBars(),
|
types = WindowInsetsCompat.Type.statusBars(),
|
||||||
showBars = !isPlayerLocked
|
showBars = !isPlayerLocked
|
||||||
)
|
)
|
||||||
|
@ -13,13 +13,13 @@ class OfflinePlayerView(
|
|||||||
override fun hideController() {
|
override fun hideController() {
|
||||||
super.hideController()
|
super.hideController()
|
||||||
// hide the status bars when continuing to watch video
|
// hide the status bars when continuing to watch video
|
||||||
activity.toggleSystemBars(WindowInsetsCompat.Type.systemBars(), false)
|
activity.window.toggleSystemBars(WindowInsetsCompat.Type.systemBars(), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showController() {
|
override fun showController() {
|
||||||
super.showController()
|
super.showController()
|
||||||
// show status bar when showing player options
|
// show status bar when showing player options
|
||||||
activity.toggleSystemBars(WindowInsetsCompat.Type.statusBars(), true)
|
activity.window.toggleSystemBars(WindowInsetsCompat.Type.statusBars(), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getTopBarMarginDp(): Int {
|
override fun getTopBarMarginDp(): Int {
|
||||||
|
@ -145,7 +145,7 @@ class OnlinePlayerView(
|
|||||||
this.playerOptions = playerOptions
|
this.playerOptions = playerOptions
|
||||||
|
|
||||||
playerViewModel.isFullscreen.observe(viewLifecycleOwner) { isFullscreen ->
|
playerViewModel.isFullscreen.observe(viewLifecycleOwner) { isFullscreen ->
|
||||||
WindowHelper.toggleFullscreen(activity, isFullscreen)
|
WindowHelper.toggleFullscreen(activity.window, isFullscreen)
|
||||||
updateTopBarMargin()
|
updateTopBarMargin()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,7 +154,7 @@ class OnlinePlayerView(
|
|||||||
playerViewModel.isFullscreen.value?.let { isFullscreen ->
|
playerViewModel.isFullscreen.value?.let { isFullscreen ->
|
||||||
if (!isFullscreen) return@let
|
if (!isFullscreen) return@let
|
||||||
// Show status bar only not navigation bar if the player controls are visible and hide it otherwise
|
// Show status bar only not navigation bar if the player controls are visible and hide it otherwise
|
||||||
activity.toggleSystemBars(
|
activity.window.toggleSystemBars(
|
||||||
types = WindowInsetsCompat.Type.statusBars(),
|
types = WindowInsetsCompat.Type.statusBars(),
|
||||||
showBars = visibility == View.VISIBLE && !isPlayerLocked
|
showBars = visibility == View.VISIBLE && !isPlayerLocked
|
||||||
)
|
)
|
||||||
@ -189,7 +189,7 @@ class OnlinePlayerView(
|
|||||||
super.hideController()
|
super.hideController()
|
||||||
|
|
||||||
if (playerViewModel?.isFullscreen?.value == true) {
|
if (playerViewModel?.isFullscreen?.value == true) {
|
||||||
WindowHelper.toggleFullscreen(activity, true)
|
WindowHelper.toggleFullscreen(activity.window, true)
|
||||||
}
|
}
|
||||||
updateTopBarMargin()
|
updateTopBarMargin()
|
||||||
}
|
}
|
||||||
|
312
app/src/main/res/layout-land/fragment_player.xml
Normal file
312
app/src/main/res/layout-land/fragment_player.xml
Normal file
@ -0,0 +1,312 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<com.github.libretube.ui.views.SingleViewTouchableMotionLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/playerMotionLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
app:layoutDescription="@xml/player_scene">
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
android:id="@+id/player_scrollView"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:background="?android:attr/colorBackground"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/related_container"
|
||||||
|
app:layout_constraintHorizontal_bias="0.5"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/main_container">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/linLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<com.github.libretube.ui.views.DescriptionLayout
|
||||||
|
android:id="@+id/descriptionLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:animateLayoutChanges="true" />
|
||||||
|
|
||||||
|
<com.google.android.material.card.MaterialCardView
|
||||||
|
style="@style/Widget.Material3.CardView.Elevated"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="10dp"
|
||||||
|
android:layout_marginVertical="17dp"
|
||||||
|
app:cardCornerRadius="27dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/optionsLL"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_marginHorizontal="8dp"
|
||||||
|
android:layout_marginVertical="18dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<com.github.libretube.ui.views.DrawableTextView
|
||||||
|
android:id="@+id/relPlayer_share"
|
||||||
|
style="@style/PlayerActionsText"
|
||||||
|
android:text="@string/share"
|
||||||
|
app:drawableTopCompat="@drawable/ic_share" />
|
||||||
|
|
||||||
|
<com.github.libretube.ui.views.DrawableTextView
|
||||||
|
android:id="@+id/relPlayer_download"
|
||||||
|
style="@style/PlayerActionsText"
|
||||||
|
android:text="@string/download"
|
||||||
|
app:drawableTopCompat="@drawable/ic_download" />
|
||||||
|
|
||||||
|
<com.github.libretube.ui.views.DrawableTextView
|
||||||
|
android:id="@+id/relPlayer_pip"
|
||||||
|
style="@style/PlayerActionsText"
|
||||||
|
android:text="@string/pop_up"
|
||||||
|
app:drawableTopCompat="@drawable/ic_open" />
|
||||||
|
|
||||||
|
<com.github.libretube.ui.views.DrawableTextView
|
||||||
|
android:id="@+id/relPlayer_background"
|
||||||
|
style="@style/PlayerActionsText"
|
||||||
|
android:text="@string/audio"
|
||||||
|
app:drawableTopCompat="@drawable/ic_headphones" />
|
||||||
|
|
||||||
|
<com.github.libretube.ui.views.DrawableTextView
|
||||||
|
android:id="@+id/relPlayer_save"
|
||||||
|
style="@style/PlayerActionsText"
|
||||||
|
android:text="@string/save"
|
||||||
|
app:drawableTopCompat="@drawable/ic_save" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/player_channel"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="8dp"
|
||||||
|
android:layout_marginVertical="10dp"
|
||||||
|
android:background="@drawable/rounded_ripple"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:padding="5dp">
|
||||||
|
|
||||||
|
<com.google.android.material.imageview.ShapeableImageView
|
||||||
|
android:id="@+id/player_channelImage"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_marginEnd="4dp"
|
||||||
|
app:shapeAppearance="@style/CircleImageView" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="start|center_vertical"
|
||||||
|
android:layout_marginStart="5dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layoutDirection="locale"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/player_channelName"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textSize="15sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/player_channelSubCount"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textSize="11sp"
|
||||||
|
tools:text="2.5M subscribers" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/player_subscribe"
|
||||||
|
style="@style/Widget.Material3.Button.ElevatedButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:text="@string/subscribe"
|
||||||
|
android:textColor="?colorControlNormal"
|
||||||
|
android:textSize="12sp"
|
||||||
|
app:cornerRadius="16dp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/alternativeTrendingRec"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
|
||||||
|
<com.google.android.material.card.MaterialCardView
|
||||||
|
android:id="@+id/comments_toggle"
|
||||||
|
style="@style/Widget.Material3.CardView.Elevated"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="12dp"
|
||||||
|
android:layout_marginVertical="16dp"
|
||||||
|
app:cardCornerRadius="18dp">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
android:paddingHorizontal="8dp"
|
||||||
|
android:text="@string/comments"
|
||||||
|
android:textAlignment="viewStart"
|
||||||
|
app:drawableEndCompat="@drawable/ic_arrow_up_down" />
|
||||||
|
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:id="@+id/main_container"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:background="?attr/colorSurface"
|
||||||
|
app:layout_constraintDimensionRatio="16:9"
|
||||||
|
app:layout_constraintWidth_percent=".55"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/related_container"
|
||||||
|
app:layout_constraintWidth_default="percent" />
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/related_container"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:animateLayoutChanges="true"
|
||||||
|
android:descendantFocusability="blocksDescendants"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/main_container"
|
||||||
|
android:background="?android:windowBackground">
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/related_rec_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
|
android:layout_marginBottom="10dp"
|
||||||
|
android:nestedScrollingEnabled="false" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<com.github.libretube.ui.views.OnlinePlayerView
|
||||||
|
android:id="@+id/player"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:background="@android:color/black"
|
||||||
|
app:controller_layout_id="@layout/exo_styled_player_control_view"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/main_container"
|
||||||
|
app:layout_constraintStart_toStartOf="@id/main_container"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/main_container"
|
||||||
|
app:layout_constraintEnd_toEndOf="@id/main_container"
|
||||||
|
app:show_buffering="when_playing">
|
||||||
|
|
||||||
|
<com.github.libretube.ui.views.DoubleTapOverlay
|
||||||
|
android:id="@+id/doubleTapOverlay"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:gravity="center" />
|
||||||
|
|
||||||
|
<com.github.libretube.ui.views.PlayerGestureControlsView
|
||||||
|
android:id="@+id/playerGestureControlsView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:gravity="center" />
|
||||||
|
|
||||||
|
<com.google.android.material.card.MaterialCardView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center|end"
|
||||||
|
android:layout_marginTop="15dp"
|
||||||
|
android:layout_marginEnd="-10dp"
|
||||||
|
android:paddingEnd="20dp"
|
||||||
|
app:cardBackgroundColor="#88000000"
|
||||||
|
app:strokeWidth="1dp"
|
||||||
|
tools:ignore="RtlSymmetry">
|
||||||
|
|
||||||
|
<com.github.libretube.ui.views.DrawableTextView
|
||||||
|
android:id="@+id/sb_skip_btn"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:drawablePadding="20dp"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:text="@string/skip_segment"
|
||||||
|
android:textColor="@android:color/white"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:drawableEndCompat="@drawable/ic_next"
|
||||||
|
app:drawableEndDimen="20dp"
|
||||||
|
app:drawableTint="@android:color/white" />
|
||||||
|
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
|
<com.github.libretube.ui.views.AutoplayCountdownView
|
||||||
|
android:id="@+id/autoplay_countdown"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
</com.github.libretube.ui.views.OnlinePlayerView>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/close_imageView"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:alpha="0"
|
||||||
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:src="@drawable/ic_close"
|
||||||
|
android:tooltipText="@string/tooltip_close"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/main_container"
|
||||||
|
app:layout_constraintEnd_toEndOf="@id/main_container"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/main_container" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/play_imageView"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:alpha="0"
|
||||||
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:src="@drawable/ic_play"
|
||||||
|
android:tooltipText="@string/tooltip_play"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/close_imageView"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/close_imageView"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/close_imageView" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/title_textView"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:alpha="0"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:paddingHorizontal="8dp"
|
||||||
|
android:paddingVertical="15dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/play_imageView"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/play_imageView"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/player"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/play_imageView" />
|
||||||
|
|
||||||
|
</com.github.libretube.ui.views.SingleViewTouchableMotionLayout>
|
@ -33,9 +33,10 @@
|
|||||||
<ConstraintSet android:id="@+id/start">
|
<ConstraintSet android:id="@+id/start">
|
||||||
<Constraint
|
<Constraint
|
||||||
android:id="@+id/player"
|
android:id="@+id/player"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
motion:layout_constraintBottom_toBottomOf="@id/main_container"
|
motion:layout_constraintBottom_toBottomOf="@id/main_container"
|
||||||
|
motion:layout_constraintEnd_toEndOf="@id/main_container"
|
||||||
motion:layout_constraintStart_toStartOf="@id/main_container"
|
motion:layout_constraintStart_toStartOf="@id/main_container"
|
||||||
motion:layout_constraintTop_toTopOf="@id/main_container" />
|
motion:layout_constraintTop_toTopOf="@id/main_container" />
|
||||||
<Constraint android:id="@+id/doubleTapOverlay" />
|
<Constraint android:id="@+id/doubleTapOverlay" />
|
||||||
|
Loading…
Reference in New Issue
Block a user