mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
tv changes for better centering + bigger text + better contrast
This commit is contained in:
parent
01e7acdeac
commit
7d6ba8c7a4
5 changed files with 107 additions and 37 deletions
|
@ -7,9 +7,14 @@ import android.content.Context
|
|||
import android.content.pm.PackageManager
|
||||
import android.content.res.Resources
|
||||
import android.os.Build
|
||||
import android.util.DisplayMetrics
|
||||
import android.util.Log
|
||||
import android.view.*
|
||||
import android.view.Gravity
|
||||
import android.view.KeyEvent
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.View.NO_ID
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.activity.ComponentActivity
|
||||
|
@ -40,7 +45,9 @@ import com.lagradost.cloudstream3.utils.UIHelper.shouldShowPIPMode
|
|||
import com.lagradost.cloudstream3.utils.UIHelper.toPx
|
||||
import org.schabi.newpipe.extractor.NewPipe
|
||||
import java.lang.ref.WeakReference
|
||||
import java.util.*
|
||||
import java.util.Locale
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
enum class FocusDirection {
|
||||
Start,
|
||||
|
@ -63,6 +70,19 @@ object CommonActivity {
|
|||
return (this as MainActivity?)?.mSessionManager?.currentCastSession
|
||||
}
|
||||
|
||||
val displayMetrics: DisplayMetrics = Resources.getSystem().displayMetrics
|
||||
|
||||
// screenWidth and screenHeight does always
|
||||
// refer to the screen while in landscape mode
|
||||
val screenWidth: Int
|
||||
get() {
|
||||
return max(displayMetrics.widthPixels, displayMetrics.heightPixels)
|
||||
}
|
||||
val screenHeight: Int
|
||||
get() {
|
||||
return min(displayMetrics.widthPixels, displayMetrics.heightPixels)
|
||||
}
|
||||
|
||||
|
||||
var canEnterPipMode: Boolean = false
|
||||
var canShowPipMode: Boolean = false
|
||||
|
@ -328,6 +348,14 @@ object CommonActivity {
|
|||
currentLook = currentLook.parent as? View ?: break
|
||||
}*/
|
||||
|
||||
private fun View.hasContent() : Boolean {
|
||||
return isShown && when(this) {
|
||||
//is RecyclerView -> this.childCount > 0
|
||||
is ViewGroup -> this.childCount > 0
|
||||
else -> true
|
||||
}
|
||||
}
|
||||
|
||||
/** skips the initial stage of searching for an id using the view, see getNextFocus for specification */
|
||||
fun continueGetNextFocus(
|
||||
root: Any?,
|
||||
|
@ -348,16 +376,17 @@ object CommonActivity {
|
|||
} ?: return null
|
||||
|
||||
next = localLook(view, nextId) ?: next
|
||||
val shown = next.hasContent()
|
||||
|
||||
// if cant focus but visible then break and let android decide
|
||||
// the exception if is the view is a parent and has children that wants focus
|
||||
val hasChildrenThatWantsFocus = (next as? ViewGroup)?.let { parent ->
|
||||
parent.descendantFocusability == ViewGroup.FOCUS_AFTER_DESCENDANTS && parent.childCount > 0
|
||||
} ?: false
|
||||
if (!next.isFocusable && next.isShown && !hasChildrenThatWantsFocus) return null
|
||||
if (!next.isFocusable && shown && !hasChildrenThatWantsFocus) return null
|
||||
|
||||
// if not shown then continue because we will "skip" over views to get to a replacement
|
||||
if (!next.isShown) {
|
||||
if (!shown) {
|
||||
// we don't want a while true loop, so we let android decide if we find a recursive view
|
||||
if (next == view) return null
|
||||
return getNextFocus(root, next, direction, depth + 1)
|
||||
|
|
|
@ -6,6 +6,7 @@ import android.content.Context
|
|||
import android.content.Intent
|
||||
import android.content.res.ColorStateList
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Rect
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
|
@ -52,6 +53,7 @@ import com.google.android.material.bottomnavigation.BottomNavigationView
|
|||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.google.android.material.navigationrail.NavigationRailView
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.google.common.collect.Comparators.min
|
||||
import com.jaredrummler.android.colorpicker.ColorPickerDialogListener
|
||||
import com.lagradost.cloudstream3.APIHolder.allProviders
|
||||
import com.lagradost.cloudstream3.APIHolder.apis
|
||||
|
@ -64,13 +66,13 @@ import com.lagradost.cloudstream3.CommonActivity.loadThemes
|
|||
import com.lagradost.cloudstream3.CommonActivity.onColorSelectedEvent
|
||||
import com.lagradost.cloudstream3.CommonActivity.onDialogDismissedEvent
|
||||
import com.lagradost.cloudstream3.CommonActivity.onUserLeaveHint
|
||||
import com.lagradost.cloudstream3.CommonActivity.screenHeight
|
||||
import com.lagradost.cloudstream3.CommonActivity.showToast
|
||||
import com.lagradost.cloudstream3.CommonActivity.updateLocale
|
||||
import com.lagradost.cloudstream3.databinding.ActivityMainBinding
|
||||
import com.lagradost.cloudstream3.databinding.ActivityMainTvBinding
|
||||
import com.lagradost.cloudstream3.databinding.BottomResultviewPreviewBinding
|
||||
import com.lagradost.cloudstream3.mvvm.Resource
|
||||
import com.lagradost.cloudstream3.mvvm.debugAssert
|
||||
import com.lagradost.cloudstream3.mvvm.logError
|
||||
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
||||
import com.lagradost.cloudstream3.mvvm.observeNullable
|
||||
|
@ -832,6 +834,13 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
|||
focusOutline.get()?.isVisible = false
|
||||
}
|
||||
}
|
||||
/*private val scrollListener = object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
super.onScrolled(recyclerView, dx, dy)
|
||||
current = current.copy(x = current.x + dx, y = current.y + dy)
|
||||
setTargetPosition(current)
|
||||
}
|
||||
}*/
|
||||
|
||||
private fun setTargetPosition(target: FocusTarget) {
|
||||
focusOutline.get()?.apply {
|
||||
|
@ -874,7 +883,10 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
|||
if (!exactlyTheSame) {
|
||||
lastView?.removeOnLayoutChangeListener(layoutListener)
|
||||
lastView?.removeOnAttachStateChangeListener(attachListener)
|
||||
(lastView?.parent as? RecyclerView)?.removeOnLayoutChangeListener(layoutListener)
|
||||
(lastView?.parent as? RecyclerView)?.apply {
|
||||
removeOnLayoutChangeListener(layoutListener)
|
||||
//removeOnScrollListener(scrollListener)
|
||||
}
|
||||
}
|
||||
|
||||
val wasGone = focusOutline.isGone
|
||||
|
@ -952,7 +964,10 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
|||
focusOutline.isVisible = false
|
||||
}
|
||||
if (!exactlyTheSame) {
|
||||
(newFocus.parent as? RecyclerView)?.addOnLayoutChangeListener(layoutListener)
|
||||
(newFocus.parent as? RecyclerView)?.apply {
|
||||
addOnLayoutChangeListener(layoutListener)
|
||||
//addOnScrollListener(scrollListener)
|
||||
}
|
||||
newFocus.addOnLayoutChangeListener(layoutListener)
|
||||
newFocus.addOnAttachStateChangeListener(attachListener)
|
||||
}
|
||||
|
@ -970,8 +985,9 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
|||
)
|
||||
|
||||
// if they are the same within then snap, aka scrolling
|
||||
val deltaMin = 50.toPx
|
||||
if (start.width == end.width && start.height == end.height && (start.x - end.x).absoluteValue < deltaMin && (start.y - end.y).absoluteValue < deltaMin) {
|
||||
val deltaMinX = min(end.width / 2, 60.toPx)
|
||||
val deltaMinY = min(end.height / 2, 60.toPx)
|
||||
if (start.width == end.width && start.height == end.height && (start.x - end.x).absoluteValue < deltaMinX && (start.y - end.y).absoluteValue < deltaMinY) {
|
||||
animator?.cancel()
|
||||
last = start
|
||||
current = end
|
||||
|
@ -1000,7 +1016,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
|||
// animate between a and b
|
||||
animator = ValueAnimator.ofFloat(0.0f, 1.0f).apply {
|
||||
startDelay = 0
|
||||
duration = 100
|
||||
duration = 200
|
||||
addUpdateListener { animation ->
|
||||
val animatedValue = animation.animatedValue as Float
|
||||
val target = FocusTarget.lerp(last, current, minOf(animatedValue, 1.0f))
|
||||
|
@ -1095,7 +1111,29 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
|||
TvFocus.focusOutline = WeakReference(newLocalBinding.focusOutline)
|
||||
newLocalBinding.root.viewTreeObserver.addOnGlobalFocusChangeListener { _, newFocus ->
|
||||
// println("refocus $oldFocus -> $newFocus")
|
||||
try {
|
||||
val r = Rect(0,0,0,0)
|
||||
newFocus.getDrawingRect(r)
|
||||
val x = r.centerX()
|
||||
val y = r.centerY()
|
||||
val dx = 0 //screenWidth / 2
|
||||
val dy = screenHeight / 2
|
||||
val r2 = Rect(x-dx,y-dy,x+dx,y+dy)
|
||||
newFocus.requestRectangleOnScreen(r2, false)
|
||||
// TvFocus.current =TvFocus.current.copy(y=y.toFloat())
|
||||
} catch (_ : Throwable) { }
|
||||
TvFocus.updateFocusView(newFocus)
|
||||
/*var focus = newFocus
|
||||
|
||||
while(focus != null) {
|
||||
if(focus is ScrollingView && focus.canScrollVertically()) {
|
||||
focus.scrollBy()
|
||||
}
|
||||
when(focus.parent) {
|
||||
is View -> focus = newFocus
|
||||
else -> break
|
||||
}
|
||||
}*/
|
||||
}
|
||||
newLocalBinding.root.viewTreeObserver.addOnScrollChangedListener {
|
||||
TvFocus.updateFocusView(TvFocus.lastFocus.get(), same = true)
|
||||
|
|
|
@ -38,6 +38,8 @@ import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
|
|||
import com.lagradost.cloudstream3.AcraApplication.Companion.setKey
|
||||
import com.lagradost.cloudstream3.CommonActivity.keyEventListener
|
||||
import com.lagradost.cloudstream3.CommonActivity.playerEventListener
|
||||
import com.lagradost.cloudstream3.CommonActivity.screenHeight
|
||||
import com.lagradost.cloudstream3.CommonActivity.screenWidth
|
||||
import com.lagradost.cloudstream3.R
|
||||
import com.lagradost.cloudstream3.databinding.PlayerCustomLayoutBinding
|
||||
import com.lagradost.cloudstream3.databinding.SubtitleOffsetBinding
|
||||
|
@ -126,19 +128,6 @@ open class FullScreenPlayer : AbstractPlayerFragment() {
|
|||
protected var useTrueSystemBrightness = true
|
||||
private val fullscreenNotch = true //TODO SETTING
|
||||
|
||||
protected val displayMetrics: DisplayMetrics = Resources.getSystem().displayMetrics
|
||||
|
||||
// screenWidth and screenHeight does always
|
||||
// refer to the screen while in landscape mode
|
||||
protected val screenWidth: Int
|
||||
get() {
|
||||
return max(displayMetrics.widthPixels, displayMetrics.heightPixels)
|
||||
}
|
||||
protected val screenHeight: Int
|
||||
get() {
|
||||
return min(displayMetrics.widthPixels, displayMetrics.heightPixels)
|
||||
}
|
||||
|
||||
private var statusBarHeight: Int? = null
|
||||
private var navigationBarHeight: Int? = null
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@ import android.view.ViewGroup
|
|||
import android.widget.FrameLayout
|
||||
import androidx.core.view.isGone
|
||||
import androidx.core.view.isVisible
|
||||
import com.lagradost.cloudstream3.CommonActivity.screenHeight
|
||||
import com.lagradost.cloudstream3.CommonActivity.screenWidth
|
||||
import com.lagradost.cloudstream3.R
|
||||
import com.lagradost.cloudstream3.ui.player.CSPlayerEvent
|
||||
import com.lagradost.cloudstream3.ui.player.PlayerEventSource
|
||||
|
|
|
@ -128,7 +128,7 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
|
|||
<FrameLayout
|
||||
android:id="@+id/background_poster_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="200dp"
|
||||
android:layout_height="150dp"
|
||||
android:visibility="visible">
|
||||
|
||||
<ImageView
|
||||
|
@ -147,8 +147,6 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
|
|||
android:src="@drawable/background_shadow">
|
||||
|
||||
</ImageView>
|
||||
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
|
||||
|
@ -411,7 +409,7 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
|
|||
android:padding="5dp"
|
||||
android:requiresFadingEdge="vertical"
|
||||
android:textColor="?attr/textColor"
|
||||
android:textSize="12sp"
|
||||
android:textSize="16sp"
|
||||
tools:text="Ryan Quicksave Romano is an eccentric adventurer with a strange power: he can create a save-point in time and redo his life whenever he dies. Arriving in New Rome, the glitzy capital of sin of a rebuilding Europe, he finds the city torn between mega-corporations, sponsored heroes, superpowered criminals, and true monsters. It's a time of chaos, where potions can grant the power to rule the world and dangers lurk everywhere. " />
|
||||
|
||||
<com.google.android.material.chip.ChipGroup
|
||||
|
@ -537,18 +535,32 @@ https://developer.android.com/design/ui/tv/samples/jet-fit
|
|||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
<ImageView
|
||||
<FrameLayout
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
android:id="@+id/episodes_shadow"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="end"
|
||||
android:clickable="false"
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
android:importantForAccessibility="no"
|
||||
android:src="@drawable/episodes_shadow"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
android:layout_height="match_parent">
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="end"
|
||||
android:clickable="false"
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
android:importantForAccessibility="no"
|
||||
android:src="@drawable/episodes_shadow"/>
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="end"
|
||||
android:clickable="false"
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
android:importantForAccessibility="no"
|
||||
android:src="@drawable/episodes_shadow"/>
|
||||
</FrameLayout>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/episode_holder_tv"
|
||||
|
|
Loading…
Reference in a new issue