Redesign player layout for tv (#479)

Co-authored-by: LagradOst <balt.758@gmail.com>
This commit is contained in:
doteq 2022-01-18 01:24:23 +01:00 committed by GitHub
parent 9f9251108a
commit 7185df6b68
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 680 additions and 61 deletions

View file

@ -37,7 +37,7 @@ object CommonActivity {
val onDialogDismissedEvent = Event<Int>() val onDialogDismissedEvent = Event<Int>()
var playerEventListener: ((PlayerEventType) -> Unit)? = null var playerEventListener: ((PlayerEventType) -> Unit)? = null
var keyEventListener: ((KeyEvent?) -> Boolean)? = null var keyEventListener: ((Pair<KeyEvent?, Boolean>) -> Boolean)? = null
var currentToast: Toast? = null var currentToast: Toast? = null
@ -134,8 +134,8 @@ object CommonActivity {
} }
} }
fun loadThemes(act: Activity? ) { fun loadThemes(act: Activity?) {
if(act == null) return if (act == null) return
val settingsManager = PreferenceManager.getDefaultSharedPreferences(act) val settingsManager = PreferenceManager.getDefaultSharedPreferences(act)
val currentTheme = val currentTheme =
@ -323,6 +323,7 @@ object CommonActivity {
val nextView = act.findViewById<View?>(next) val nextView = act.findViewById<View?>(next)
if (nextView != null) { if (nextView != null) {
nextView.requestFocus() nextView.requestFocus()
keyEventListener?.invoke(Pair(event, true))
return true return true
} }
} }
@ -345,7 +346,7 @@ object CommonActivity {
} }
} }
if (keyEventListener?.invoke(event) == true) { if (keyEventListener?.invoke(Pair(event, false)) == true) {
return true return true
} }
return null return null

View file

@ -58,7 +58,6 @@ const val PRELOAD_NEXT_EPISODE_PERCENTAGE = 80
const val NEXT_WATCH_EPISODE_PERCENTAGE = 95 const val NEXT_WATCH_EPISODE_PERCENTAGE = 95
abstract class AbstractPlayerFragment( abstract class AbstractPlayerFragment(
@LayoutRes val layout: Int,
val player: IPlayer = CS3IPlayer() val player: IPlayer = CS3IPlayer()
) : Fragment() { ) : Fragment() {
var resizeMode: Int = 0 var resizeMode: Int = 0
@ -66,6 +65,9 @@ abstract class AbstractPlayerFragment(
var subView: SubtitleView? = null var subView: SubtitleView? = null
var isBuffering = true var isBuffering = true
@LayoutRes
protected var layout: Int = R.layout.fragment_player
open fun nextEpisode() { open fun nextEpisode() {
throw NotImplementedError() throw NotImplementedError()
} }
@ -78,12 +80,12 @@ abstract class AbstractPlayerFragment(
throw NotImplementedError() throw NotImplementedError()
} }
open fun playerDimensionsLoaded(widthHeight : Pair<Int, Int>) { open fun playerDimensionsLoaded(widthHeight: Pair<Int, Int>) {
throw NotImplementedError() throw NotImplementedError()
} }
private fun keepScreenOn(on : Boolean) { private fun keepScreenOn(on: Boolean) {
if(on) { if (on) {
activity?.window?.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) activity?.window?.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
} else { } else {
activity?.window?.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) activity?.window?.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
@ -128,7 +130,7 @@ abstract class AbstractPlayerFragment(
} }
// somehow the phone is wacked // somehow the phone is wacked
if(!startedAnimation) { if (!startedAnimation) {
player_pause_play?.setImageResource(if (isPlayingRightNow) R.drawable.netflix_pause else R.drawable.netflix_play) player_pause_play?.setImageResource(if (isPlayingRightNow) R.drawable.netflix_pause else R.drawable.netflix_play)
} }
} else { } else {

View file

@ -56,7 +56,7 @@ const val DOUBLE_TAB_MINIMUM_TIME_BETWEEN = 200L // this also affects the UI
const val DOUBLE_TAB_PAUSE_PERCENTAGE = 0.15 // in both directions const val DOUBLE_TAB_PAUSE_PERCENTAGE = 0.15 // in both directions
// All the UI Logic for the player // All the UI Logic for the player
open class FullScreenPlayer : AbstractPlayerFragment(R.layout.fragment_player) { open class FullScreenPlayer : AbstractPlayerFragment() {
// state of player UI // state of player UI
protected var isShowing = false protected var isShowing = false
protected var isLocked = false protected var isLocked = false
@ -352,6 +352,7 @@ open class FullScreenPlayer : AbstractPlayerFragment(R.layout.fragment_player) {
} }
activity?.hideSystemUI() activity?.hideSystemUI()
animateLayoutChanges() animateLayoutChanges()
player_pause_play.requestFocus()
} }
private fun toggleLock() { private fun toggleLock() {
@ -413,13 +414,15 @@ open class FullScreenPlayer : AbstractPlayerFragment(R.layout.fragment_player) {
private fun updateLockUI() { private fun updateLockUI() {
player_lock?.setIconResource(if (isLocked) R.drawable.video_locked else R.drawable.video_unlocked) player_lock?.setIconResource(if (isLocked) R.drawable.video_locked else R.drawable.video_unlocked)
val color = if (isLocked) context?.colorFromAttribute(R.attr.colorPrimary) if (layout == R.layout.fragment_player) {
else Color.WHITE val color = if (isLocked) context?.colorFromAttribute(R.attr.colorPrimary)
if (color != null) { else Color.WHITE
player_lock?.setTextColor(color) if (color != null) {
player_lock?.iconTint = ColorStateList.valueOf(color) player_lock?.setTextColor(color)
player_lock?.rippleColor = player_lock?.iconTint = ColorStateList.valueOf(color)
ColorStateList.valueOf(Color.argb(50, color.red, color.green, color.blue)) player_lock?.rippleColor =
ColorStateList.valueOf(Color.argb(50, color.red, color.green, color.blue))
}
} }
} }
@ -819,50 +822,71 @@ open class FullScreenPlayer : AbstractPlayerFragment(R.layout.fragment_player) {
return true return true
} }
private fun handleKeyEvent(event: KeyEvent): Boolean { private fun handleKeyEvent(event: KeyEvent, hasNavigated: Boolean): Boolean {
event.keyCode.let { keyCode -> if (hasNavigated) {
when (event.action) { autoHide()
KeyEvent.ACTION_DOWN -> { } else {
when (keyCode) { event.keyCode.let { keyCode ->
KeyEvent.KEYCODE_DPAD_CENTER, KeyEvent.KEYCODE_DPAD_UP -> { when (event.action) {
if (!isShowing) { KeyEvent.ACTION_DOWN -> {
onClickChange() when (keyCode) {
return true KeyEvent.KEYCODE_DPAD_CENTER -> {
if (!isShowing) {
if (!isLocked) player.handleEvent(CSPlayerEvent.PlayPauseToggle)
onClickChange()
return true
}
}
KeyEvent.KEYCODE_DPAD_UP -> {
if (!isShowing) {
onClickChange()
return true
}
}
KeyEvent.KEYCODE_DPAD_LEFT -> {
if (!isShowing && !isLocked) {
player.seekTime(-10000L)
return true
} else if (player_pause_play?.isFocused == true) {
player.seekTime(-30000L)
return true
}
}
KeyEvent.KEYCODE_DPAD_RIGHT -> {
if (!isShowing && !isLocked) {
player.seekTime(10000L)
return true
} else if (player_pause_play?.isFocused == true) {
player.seekTime(30000L)
return true
}
} }
} }
} }
//println("Keycode: $keyCode")
//showToast(
// this,
// "Got Keycode $keyCode | ${KeyEvent.keyCodeToString(keyCode)} \n ${event?.action}",
// Toast.LENGTH_LONG
//)
} }
}
when (keyCode) { when (keyCode) {
// don't allow dpad move when hidden // don't allow dpad move when hidden
KeyEvent.KEYCODE_DPAD_LEFT,
KeyEvent.KEYCODE_DPAD_DOWN, KeyEvent.KEYCODE_DPAD_DOWN,
KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_DPAD_UP,
KeyEvent.KEYCODE_DPAD_RIGHT, KeyEvent.KEYCODE_DPAD_DOWN_LEFT,
KeyEvent.KEYCODE_DPAD_DOWN_LEFT, KeyEvent.KEYCODE_DPAD_DOWN_RIGHT,
KeyEvent.KEYCODE_DPAD_DOWN_RIGHT, KeyEvent.KEYCODE_DPAD_UP_LEFT,
KeyEvent.KEYCODE_DPAD_UP_LEFT, KeyEvent.KEYCODE_DPAD_UP_RIGHT -> {
KeyEvent.KEYCODE_DPAD_UP_RIGHT -> { if (!isShowing) {
if (!isShowing) { return true
return true } else {
} else { autoHide()
autoHide() }
} }
}
// netflix capture back and hide ~monke // netflix capture back and hide ~monke
KeyEvent.KEYCODE_BACK -> { KeyEvent.KEYCODE_BACK -> {
if (isShowing) { if (isShowing) {
onClickChange() onClickChange()
return true return true
}
} }
} }
} }
@ -940,12 +964,11 @@ open class FullScreenPlayer : AbstractPlayerFragment(R.layout.fragment_player) {
} }
// handle tv controls directly based on player state // handle tv controls directly based on player state
keyEventListener = { keyEvent -> keyEventListener = { eventNav ->
if (keyEvent != null) { val (event, hasNavigated) = eventNav
handleKeyEvent(keyEvent) if (event != null)
} else { handleKeyEvent(event, hasNavigated)
false else false
}
} }
try { try {

View file

@ -22,6 +22,7 @@ import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
import com.lagradost.cloudstream3.mvvm.observe import com.lagradost.cloudstream3.mvvm.observe
import com.lagradost.cloudstream3.ui.player.PlayerSubtitleHelper.Companion.toSubtitleMimeType import com.lagradost.cloudstream3.ui.player.PlayerSubtitleHelper.Companion.toSubtitleMimeType
import com.lagradost.cloudstream3.ui.result.ResultEpisode import com.lagradost.cloudstream3.ui.result.ResultEpisode
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
import com.lagradost.cloudstream3.ui.subtitles.SubtitlesFragment import com.lagradost.cloudstream3.ui.subtitles.SubtitlesFragment
import com.lagradost.cloudstream3.utils.* import com.lagradost.cloudstream3.utils.*
import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe
@ -279,7 +280,7 @@ class GeneratorPlayer : FullScreenPlayer() {
sourceDialog.dismissSafe(activity) sourceDialog.dismissSafe(activity)
} }
} }
} catch (e : Exception) { } catch (e: Exception) {
logError(e) logError(e)
} }
} }
@ -485,6 +486,10 @@ class GeneratorPlayer : FullScreenPlayer() {
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View? {
// this is used instead of layout-television to follow the settings and some TV devices are not classified as TV for some reason
layout =
if (context?.isTvSettings() == true) R.layout.fragment_player_tv else R.layout.fragment_player
viewModel = ViewModelProvider(this)[PlayerGeneratorViewModel::class.java] viewModel = ViewModelProvider(this)[PlayerGeneratorViewModel::class.java]
viewModel.attachGenerator(lastUsedGenerator) viewModel.attachGenerator(lastUsedGenerator)
return super.onCreateView(inflater, container, savedInstanceState) return super.onCreateView(inflater, container, savedInstanceState)

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true" android:color="#FFFFFF"/>
<item android:color="#33FFFFFF"/>
</selector>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true" android:color="@color/black"/>
<item android:color="@color/white"/>
</selector>

View file

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true">
<shape android:shape="rectangle">
<solid android:color="#FFFFFF" />
<corners android:radius="3dp"/>
</shape>
</item>
<item>
<shape android:shape="rectangle">
<solid android:color="#33FFFFFF" />
<corners android:radius="3dp"/>
</shape>
</item>
</selector>

View file

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<gradient
android:angle="90"
android:startColor="#000000"
android:centerColor="#00000000"
android:endColor="#00000000"
android:centerY="0.7"
/>
</shape>
</item>
<item>
<shape>
<gradient
android:angle="270"
android:startColor="#000000"
android:centerColor="#00000000"
android:endColor="#00000000"
android:centerY="0.7"
/>
</shape>
</item>
</layer-list>

View file

@ -0,0 +1,138 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:keepScreenOn="true"
android:id="@+id/player_background"
app:backgroundTint="@android:color/black"
android:background="@android:color/black"
android:screenOrientation="sensorLandscape"
app:surface_type="texture_view"
>
<!--
app:fastforward_increment="10000"
app:rewind_increment="10000"-->
<com.google.android.exoplayer2.ui.PlayerView
android:id="@+id/player_view"
app:show_timeout="0"
app:hide_on_touch="false"
app:auto_show="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:controller_layout_id="@layout/player_custom_layout_tv"
/>
<FrameLayout
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/player_loading_overlay"
android:background="@android:color/black"
android:backgroundTint="@android:color/black"
>
<com.google.android.material.button.MaterialButton
tools:visibility="visible"
android:visibility="gone"
android:layout_marginTop="70dp"
android:layout_gravity="center"
app:cornerRadius="4dp"
android:id="@+id/overlay_loading_skip_button"
android:text="@string/skip_loading"
app:rippleColor="?attr/colorPrimary"
android:textColor="?attr/textColor"
app:iconTint="?attr/textColor"
android:textAllCaps="false"
app:icon="@drawable/ic_baseline_skip_next_24"
android:backgroundTint="@color/transparent"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:layout_width="wrap_content"
android:layout_height="45dp">
</com.google.android.material.button.MaterialButton>
<ProgressBar
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="center"
android:id="@+id/main_load"
>
</ProgressBar>
<FrameLayout
android:id="@+id/video_go_back_holder_holder"
android:layout_margin="5dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="center"
android:src="@drawable/ic_baseline_arrow_back_24"
app:tint="@android:color/white"
>
</ImageView>
<ImageView
android:id="@+id/player_loading_go_back"
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_gravity="center"
android:focusable="true"
android:clickable="true"
android:background="@drawable/video_tap_button_always_white">
</ImageView>
</FrameLayout>
</FrameLayout>
<FrameLayout
android:visibility="gone"
android:paddingStart="20dp"
android:paddingEnd="20dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:id="@+id/player_torrent_info"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:gravity="start"
android:layout_marginTop="15dp"
android:textStyle="bold"
android:textColor="@color/white"
android:id="@+id/video_torrent_progress"
tools:text="78% at 18kb/s"
>
</TextView>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
android:gravity="start"
android:layout_marginTop="0dp"
android:textColor="@color/white"
android:id="@+id/video_torrent_seeders"
tools:text="17 seeders"
app:layout_constraintTop_toBottomOf="@+id/player_video_title">
</TextView>
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -0,0 +1,373 @@
<FrameLayout 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/player_holder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:screenOrientation="landscape"
tools:orientation="vertical"
android:tag="television">
<FrameLayout
android:id="@+id/subtitle_holder"
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:id="@+id/shadow_overlay"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/player_gradient_tv" />
</FrameLayout>
<!--
<LinearLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="end"
android:id="@+id/video_lock_holder"
>
<FrameLayout
android:layout_margin="5dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:ignore="UselessParent">
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_margin="20dp"
android:id="@+id/video_locked_img"
android:layout_gravity="end|center_vertical"
android:src="@drawable/video_locked">
</ImageView>
<ImageView
android:id="@+id/video_lock"
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_gravity="end|center_vertical"
android:focusable="true"
android:clickable="true"
android:background="@drawable/video_tap_button_always_white">
</ImageView>
</FrameLayout>
</LinearLayout>
-->
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/player_video_holder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<FrameLayout
android:id="@+id/player_top_holder"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/player_video_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="80dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="32dp"
android:gravity="end"
android:textColor="@color/white"
android:textSize="16sp"
android:textStyle="bold"
tools:text="Hello world" />
<TextView
android:id="@+id/player_video_title_rez"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="80dp"
android:layout_marginTop="40dp"
android:layout_marginEnd="32dp"
android:gravity="end"
android:textColor="@color/white"
android:textSize="16sp"
tools:text="1920x1080" />
<!-- Removed as it has no use anymore-->
<!--<androidx.mediarouter.app.MediaRouteButton
android:id="@+id/player_media_route_button"
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_gravity="end"
android:layout_margin="5dp"
android:mediaRouteTypes="user"
android:visibility="visible"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />-->
<FrameLayout
android:id="@+id/player_go_back_holder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="center"
android:src="@drawable/ic_baseline_arrow_back_24"
app:tint="@android:color/white"
android:contentDescription="@string/go_back_img_des" />
<ImageView
android:id="@+id/player_go_back"
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_gravity="center"
android:background="@drawable/video_tap_button_always_white"
android:clickable="true"
android:contentDescription="@string/go_back_img_des"
android:focusable="true" />
</FrameLayout>
</FrameLayout>
<!--use for thinner app:trackThickness="3dp" com.google.android.material.progressindicator.CircularProgressIndicator-->
<ProgressBar
android:id="@+id/player_buffering"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"
android:indeterminate="true"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginBottom="20dp"
android:gravity="center"
android:orientation="horizontal"
android:paddingTop="4dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<ImageButton
android:id="@id/exo_prev"
style="@style/ExoMediaButton.Previous"
android:tintMode="src_in"
app:tint="?attr/colorPrimaryDark"
tools:ignore="ContentDescription" />
<ImageButton
android:id="@id/exo_repeat_toggle"
style="@style/ExoMediaButton"
android:tintMode="src_in"
app:tint="?attr/colorPrimaryDark"
tools:ignore="ContentDescription" />
<ImageButton
android:id="@id/exo_next"
style="@style/ExoMediaButton.Next"
android:tintMode="src_in"
app:tint="?attr/colorPrimaryDark"
tools:ignore="ContentDescription" />
<ImageButton
android:id="@id/exo_vr"
style="@style/ExoMediaButton.VR"
android:tintMode="src_in"
app:tint="?attr/colorPrimaryDark"
tools:ignore="ContentDescription" />
<ImageButton
android:id="@id/exo_play"
android:layout_width="0dp"
android:layout_height="0dp"
android:tintMode="src_in"
app:tint="?attr/colorPrimaryDark"
tools:ignore="ContentDescription" />
<ImageButton
android:id="@id/exo_pause"
android:layout_width="0dp"
android:layout_height="0dp"
android:tintMode="src_in"
app:tint="?attr/colorPrimaryDark"
tools:ignore="ContentDescription" />
</LinearLayout>
<LinearLayout
android:id="@+id/bottom_player_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="64dp"
android:layout_marginEnd="64dp"
android:layout_marginBottom="10dp"
android:gravity="center_vertical"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<LinearLayout
android:id="@+id/player_video_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/player_pause_play"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="center"
android:layout_marginStart="20dp"
android:background="@drawable/video_tap_button"
android:focusable="true"
android:focusableInTouchMode="true"
android:nextFocusUp="@id/player_go_back"
android:nextFocusDown="@id/player_lock"
android:src="@drawable/netflix_pause"
app:tint="@color/player_button_tv"
tools:ignore="ContentDescription" />
<TextView
android:id="@id/exo_position"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="end"
android:includeFontPadding="false"
android:minWidth="50dp"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:textColor="@android:color/white"
android:textSize="14sp"
android:textStyle="normal"
tools:text="15:30" />
<!--app:buffered_color="@color/videoCache"-->
<com.google.android.exoplayer2.ui.DefaultTimeBar
android:id="@id/exo_progress"
android:layout_width="0dp"
android:layout_height="30dp"
android:layout_gravity="center"
android:layout_weight="1"
android:focusable="false"
android:focusableInTouchMode="false"
app:bar_height="2dp"
app:played_color="?attr/colorPrimary"
app:scrubber_color="?attr/colorPrimary"
app:scrubber_dragged_size="26dp"
app:scrubber_enabled_size="24dp"
app:unplayed_color="@color/videoProgress" />
<!-- exo_duration-->
<TextView
android:id="@id/exo_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginEnd="20dp"
android:includeFontPadding="false"
android:minWidth="50dp"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:textColor="@android:color/white"
android:textSize="14sp"
android:textStyle="normal"
tools:text="23:20" />
</LinearLayout>
<HorizontalScrollView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingTop="10dp"
android:paddingBottom="10dp">
<com.google.android.material.button.MaterialButton
android:id="@+id/player_lock"
style="@style/VideoButtonTV"
android:nextFocusLeft="@id/player_skip_episode"
android:nextFocusRight="@id/player_resize_btt"
android:nextFocusUp="@id/player_pause_play"
android:text="@string/video_lock"
app:icon="@drawable/video_locked" />
<LinearLayout
android:id="@+id/player_lock_holder"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal">
<com.google.android.material.button.MaterialButton
android:id="@+id/player_resize_btt"
style="@style/VideoButtonTV"
android:nextFocusLeft="@id/player_lock"
android:nextFocusRight="@id/player_speed_btt"
android:nextFocusUp="@id/player_pause_play"
android:text="@string/video_aspect_ratio_resize"
app:icon="@drawable/ic_baseline_aspect_ratio_24" />
<com.google.android.material.button.MaterialButton
android:id="@+id/player_speed_btt"
style="@style/VideoButtonTV"
android:nextFocusLeft="@id/player_resize_btt"
android:nextFocusRight="@id/player_sources_btt"
android:nextFocusUp="@id/player_pause_play"
app:icon="@drawable/ic_baseline_speed_24"
tools:text="Speed" />
<com.google.android.material.button.MaterialButton
android:id="@+id/player_sources_btt"
style="@style/VideoButtonTV"
android:nextFocusLeft="@id/player_speed_btt"
android:nextFocusRight="@id/player_skip_op"
android:nextFocusUp="@id/player_pause_play"
android:text="@string/video_source"
app:icon="@drawable/ic_baseline_playlist_play_24" />
<com.google.android.material.button.MaterialButton
android:id="@+id/player_skip_op"
style="@style/VideoButtonTV"
android:nextFocusLeft="@id/player_sources_btt"
android:nextFocusRight="@id/player_skip_episode"
android:nextFocusUp="@id/player_pause_play"
android:text="@string/video_skip_op"
app:icon="@drawable/ic_baseline_fast_forward_24" />
<com.google.android.material.button.MaterialButton
android:id="@+id/player_skip_episode"
style="@style/VideoButtonTV"
android:nextFocusLeft="@id/player_skip_op"
android:nextFocusRight="@id/player_lock"
android:nextFocusUp="@id/player_pause_play"
android:text="@string/next_episode"
app:icon="@drawable/ic_baseline_skip_next_24" />
</LinearLayout>
</LinearLayout>
</HorizontalScrollView>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>

View file

@ -421,6 +421,32 @@
<item name="android:layout_marginEnd">10dp</item> <item name="android:layout_marginEnd">10dp</item>
</style> </style>
<style name="VideoButtonTV">
<item name="android:stateListAnimator">@null</item>
<item name="strokeColor">@color/transparent</item>
<item name="backgroundTint">@null</item>
<item name="android:background">@drawable/player_button_tv</item>
<item name="rippleColor">@color/white</item>
<item name="android:shadowColor">@color/transparent</item>
<item name="iconTint">@color/player_on_button_tv</item>
<item name="textColor">@color/player_on_button_tv</item>
<item name="android:textColor">@color/player_on_button_tv</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">25dp</item>
<item name="iconSize">16dp</item>
<item name="android:gravity">center</item>
<item name="android:layout_gravity">center</item>
<item name="android:baselineAligned">false</item>
<item name="textAllCaps">false</item>
<item name="android:textStyle">bold</item>
<item name="android:textSize">10sp</item>
<item name="android:layout_marginStart">4dp</item>
<item name="android:layout_marginEnd">4dp</item>
<item name="android:insetBottom">0dp</item>
<item name="android:insetTop">0dp</item>
</style>
<!--@color/white ?attr/colorPrimary--> <!--@color/white ?attr/colorPrimary-->
<!--CHECK ?attr/darkBackground ?attr/colorPrimary--> <!--CHECK ?attr/darkBackground ?attr/colorPrimary-->
<!-- CHROMECAST --> <!-- CHROMECAST -->