fixed tv focus issue

This commit is contained in:
LagradOst 2023-08-02 21:00:04 +02:00
parent c5f6f36fc7
commit 7e6a28bb99
5 changed files with 118 additions and 14 deletions

View File

@ -301,7 +301,8 @@ object CommonActivity {
private fun localLook(from: View, id: Int): View? {
if (id == NO_ID) return null
var currentLook: View = from
while (true) {
// limit to 15 look depth
for (i in 0..15) {
currentLook.findViewById<View?>(id)?.let { return it }
currentLook = (currentLook.parent as? View) ?: break
}
@ -359,18 +360,14 @@ object CommonActivity {
// if not specified then use forward id
nextId = view.nextFocusForwardId
// if view is still not found to next focus then return and let android decide
if (nextId == NO_ID) return null
if (nextId == NO_ID)
return null
}
var next = act.findViewById<View?>(nextId) ?: return null
next = localLook(view, nextId) ?: next
var currentLook: View = view
while (currentLook.findViewById<View?>(nextId)?.also { next = it } == null) {
currentLook = (currentLook.parent as? View) ?: break
}
// 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 ->
@ -520,7 +517,7 @@ object CommonActivity {
else -> null
}
// println("NEXT FOCUS : $nextView")
if (nextView != null) {
nextView.requestFocus()
keyEventListener?.invoke(Pair(event, true))

View File

@ -27,6 +27,7 @@ import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.children
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.core.view.marginStart
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.NavController
@ -37,6 +38,8 @@ import androidx.navigation.NavOptions
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.setupWithNavController
import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.LinearSnapHelper
import androidx.recyclerview.widget.RecyclerView
import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.ObjectMapper
@ -91,6 +94,7 @@ import com.lagradost.cloudstream3.ui.home.HomeViewModel
import com.lagradost.cloudstream3.ui.player.BasicLink
import com.lagradost.cloudstream3.ui.player.GeneratorPlayer
import com.lagradost.cloudstream3.ui.player.LinkGenerator
import com.lagradost.cloudstream3.ui.result.LinearListLayout
import com.lagradost.cloudstream3.ui.result.ResultViewModel2
import com.lagradost.cloudstream3.ui.result.START_ACTION_RESUME_LATEST
import com.lagradost.cloudstream3.ui.result.setImage
@ -110,6 +114,7 @@ import com.lagradost.cloudstream3.utils.AppUtils.html
import com.lagradost.cloudstream3.utils.AppUtils.isCastApiAvailable
import com.lagradost.cloudstream3.utils.AppUtils.isLtr
import com.lagradost.cloudstream3.utils.AppUtils.isNetworkAvailable
import com.lagradost.cloudstream3.utils.AppUtils.isRtl
import com.lagradost.cloudstream3.utils.AppUtils.loadCache
import com.lagradost.cloudstream3.utils.AppUtils.loadRepository
import com.lagradost.cloudstream3.utils.AppUtils.loadResult
@ -146,6 +151,7 @@ import java.lang.ref.WeakReference
import java.net.URI
import java.net.URLDecoder
import java.nio.charset.Charset
import kotlin.math.abs
import kotlin.math.absoluteValue
import kotlin.reflect.KClass
import kotlin.system.exitProcess
@ -848,6 +854,24 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
private var animator: ValueAnimator? = null
/** if this is enabled it will keep the focus unmoving
* during listview move */
private const val NO_MOVE_LIST: Boolean = false
/** If this is enabled then it will try to move the
* listview focus to the left instead of center */
private const val LEFTMOST_MOVE_LIST: Boolean = true
private val reflectedScroll by lazy {
try {
RecyclerView::class.java.declaredMethods.firstOrNull {
it.name == "scrollStep"
}?.also { it.isAccessible = true }
} catch (t : Throwable) {
null
}
}
@MainThread
fun updateFocusView(newFocus: View?, same: Boolean = false) {
val focusOutline = focusOutline.get() ?: return
@ -867,17 +891,67 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
if (newFocus != null) {
lastFocus = WeakReference(newFocus)
val parent = newFocus.parent
var targetDx = 0
if (parent is RecyclerView) {
val layoutManager = parent.layoutManager
if (layoutManager is LinearListLayout && layoutManager.orientation == LinearLayoutManager.HORIZONTAL) {
val dx =
LinearSnapHelper().calculateDistanceToFinalSnap(layoutManager, newFocus)
?.get(0)
if (dx != null) {
val rdx = if (LEFTMOST_MOVE_LIST) {
// this makes the item the leftmost in ltr, instead of center
val diff =
((layoutManager.width - layoutManager.paddingStart - newFocus.measuredWidth) / 2) - newFocus.marginStart
dx + if (parent.isRtl()) {
-diff
} else {
diff
}
} else {
if (dx > 0) dx else 0
}
if(!NO_MOVE_LIST) {
parent.smoothScrollBy(rdx, 0)
}else {
val smoothScroll = reflectedScroll
if(smoothScroll == null) {
parent.smoothScrollBy(rdx, 0)
} else {
try {
// this is very fucked but because it is a protected method to
// be able to compute the scroll I use reflection, scroll, then
// scroll back, then smooth scroll and set the no move
val out = IntArray(2)
smoothScroll.invoke(parent, rdx, 0, out)
val scrolledX = out[0]
if(abs(scrolledX) <= 0) { // newFocus.measuredWidth*2
smoothScroll.invoke(parent, -rdx, 0, out)
parent.smoothScrollBy(scrolledX, 0)
if (NO_MOVE_LIST) targetDx = scrolledX
}
} catch (t : Throwable) {
parent.smoothScrollBy(rdx, 0)
}
}
}
}
}
}
val out = IntArray(2)
newFocus.getLocationInWindow(out)
val (screenX, screenY) = out
var (x, y) = screenX.toFloat() to screenY.toFloat()
val (currentX, currentY) = focusOutline.translationX to focusOutline.translationY
// println(">><<< $x $y $currentX $currentY")
if (!newFocus.isLtr()) {
x = x - focusOutline.rootView.width + newFocus.measuredWidth
}
x -= targetDx
// out of bounds = 0,0
if (screenX == 0 && screenY == 0) {
@ -1093,9 +1167,17 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
}
//Automatically download not existing plugins, using mode specified.
val auto_download_plugin = AutoDownloadMode.getEnum(settingsManager.getInt(getString(R.string.auto_download_plugins_key), 0)) ?: AutoDownloadMode.Disable
val auto_download_plugin = AutoDownloadMode.getEnum(
settingsManager.getInt(
getString(R.string.auto_download_plugins_key),
0
)
) ?: AutoDownloadMode.Disable
if (auto_download_plugin != AutoDownloadMode.Disable) {
PluginManager.downloadNotExistingPluginsAndLoad(this@MainActivity, auto_download_plugin)
PluginManager.downloadNotExistingPluginsAndLoad(
this@MainActivity,
auto_download_plugin
)
}
}

View File

@ -14,6 +14,7 @@ import androidx.viewbinding.ViewBinding
import androidx.viewpager2.widget.ViewPager2
import com.google.android.material.chip.Chip
import com.google.android.material.chip.ChipDrawable
import com.google.android.material.chip.ChipGroup
import com.lagradost.cloudstream3.APIHolder.getId
import com.lagradost.cloudstream3.AcraApplication.Companion.getActivity
import com.lagradost.cloudstream3.CommonActivity.activity
@ -416,6 +417,7 @@ class HomeParentItemAdapterPreview(
isChecked = checked.contains(watch)
}
}
toggleListHolder?.isGone = visible.isEmpty()
}
} ?: debugException { "Expected findViewTreeLifecycleOwner" }
}
@ -428,6 +430,8 @@ class HomeParentItemAdapterPreview(
Pair(itemView.findViewById(R.id.home_plan_to_watch_btt), WatchType.PLANTOWATCH),
)
private val toggleListHolder : ChipGroup? = itemView.findViewById(R.id.home_type_holder)
init {
previewViewpager.setPageTransformer(HomeScrollTransformer())

View File

@ -153,6 +153,7 @@
android:layout_marginStart="@dimen/navbar_width"
android:backgroundTint="@color/semiWhite"
android:minWidth="150dp"
android:nextFocusUp="@id/home_preview_play_btt"
android:nextFocusLeft="@id/nav_rail_view"
android:nextFocusDown="@id/home_watch_child_recyclerview" />
</FrameLayout>
@ -178,6 +179,8 @@
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/home_watch_child_recyclerview"
android:nextFocusUp="@id/home_preview_change_api2"
android:nextFocusDown="@id/home_type_holder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clipToPadding="false"
@ -204,9 +207,6 @@
android:fadingEdge="horizontal"
android:foreground="?android:attr/selectableItemBackgroundBorderless"
android:nextFocusLeft="@id/nav_rail_view"
android:nextFocusUp="@id/home_watch_child_recyclerview"
android:nextFocusForward="@id/home_bookmarked_child_recyclerview"
android:paddingStart="12dp"
android:paddingTop="5dp"
android:paddingEnd="12dp"
@ -215,6 +215,12 @@
android:requiresFadingEdge="horizontal">
<com.google.android.material.chip.ChipGroup
android:id="@+id/home_type_holder"
android:nextFocusLeft="@id/nav_rail_view"
android:nextFocusUp="@id/home_watch_child_recyclerview"
android:nextFocusDown="@id/home_bookmarked_child_recyclerview"
android:descendantFocusability="afterDescendants"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/navbar_width"
@ -225,6 +231,8 @@
style="@style/ChipFilled"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:nextFocusUp="@id/home_watch_child_recyclerview"
android:nextFocusDown="@id/home_bookmarked_child_recyclerview"
android:nextFocusLeft="@id/nav_rail_view"
android:nextFocusRight="@id/home_plan_to_watch_btt"
@ -235,6 +243,8 @@
style="@style/ChipFilled"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:nextFocusUp="@id/home_watch_child_recyclerview"
android:nextFocusDown="@id/home_bookmarked_child_recyclerview"
android:nextFocusLeft="@id/home_type_watching_btt"
android:nextFocusRight="@id/home_type_on_hold_btt"
@ -245,6 +255,8 @@
style="@style/ChipFilled"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:nextFocusUp="@id/home_watch_child_recyclerview"
android:nextFocusDown="@id/home_bookmarked_child_recyclerview"
android:nextFocusLeft="@id/home_plan_to_watch_btt"
android:nextFocusRight="@id/home_type_dropped_btt"
@ -255,6 +267,8 @@
style="@style/ChipFilled"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:nextFocusUp="@id/home_watch_child_recyclerview"
android:nextFocusDown="@id/home_bookmarked_child_recyclerview"
android:nextFocusLeft="@id/home_type_on_hold_btt"
android:nextFocusRight="@id/home_type_completed_btt"
@ -264,6 +278,8 @@
android:id="@+id/home_type_completed_btt"
style="@style/ChipFilled"
android:layout_width="wrap_content"
android:nextFocusUp="@id/home_watch_child_recyclerview"
android:nextFocusDown="@id/home_bookmarked_child_recyclerview"
android:layout_height="wrap_content"
android:nextFocusLeft="@id/home_type_dropped_btt"
@ -273,6 +289,10 @@
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/home_bookmarked_child_recyclerview"
android:nextFocusUp="@id/home_type_holder"
android:nextFocusLeft="@id/nav_rail_view"
android:nextFocusDown="@id/home_child_recyclerview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clipToPadding="false"

View File

@ -162,6 +162,7 @@
android:layout_height="wrap_content"
android:descendantFocusability="afterDescendants"
android:nextFocusLeft="@id/nav_rail_view"
android:nextFocusUp="@id/home_bookmarked_child_recyclerview"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/homepage_parent_tv" />