testing follow focus on tv

This commit is contained in:
LagradOst 2023-07-24 04:02:05 +02:00
parent 51a6e917b5
commit 3e4a5bdf4c
7 changed files with 164 additions and 62 deletions

View file

@ -83,7 +83,7 @@ object CommonActivity {
val act = activity ?: return
if (message == null) return
act.runOnUiThread {
showToast(act, message.asString(act), duration)
showToast(act, message.asString(act), duration)
}
}
@ -443,63 +443,58 @@ object CommonActivity {
fun dispatchKeyEvent(act: Activity?, event: KeyEvent?): Boolean? {
if (act == null) return null
val currentFocus = act.currentFocus
event?.keyCode?.let { keyCode ->
when (event.action) {
KeyEvent.ACTION_DOWN -> {
if (act.currentFocus != null) {
val next = when (keyCode) {
KeyEvent.KEYCODE_DPAD_LEFT -> getNextFocus(
act,
act.currentFocus,
FocusDirection.Left
)
if (currentFocus == null || event.action != KeyEvent.ACTION_DOWN) return@let
val next = when (keyCode) {
KeyEvent.KEYCODE_DPAD_LEFT -> getNextFocus(
act,
currentFocus,
FocusDirection.Left
)
KeyEvent.KEYCODE_DPAD_RIGHT -> getNextFocus(
act,
act.currentFocus,
FocusDirection.Right
)
KeyEvent.KEYCODE_DPAD_RIGHT -> getNextFocus(
act,
currentFocus,
FocusDirection.Right
)
KeyEvent.KEYCODE_DPAD_UP -> getNextFocus(
act,
act.currentFocus,
FocusDirection.Up
)
KeyEvent.KEYCODE_DPAD_UP -> getNextFocus(
act,
currentFocus,
FocusDirection.Up
)
KeyEvent.KEYCODE_DPAD_DOWN -> getNextFocus(
act,
act.currentFocus,
FocusDirection.Down
)
KeyEvent.KEYCODE_DPAD_DOWN -> getNextFocus(
act,
currentFocus,
FocusDirection.Down
)
else -> null
}
else -> null
}
if (next != null && next != -1) {
val nextView = act.findViewById<View?>(next)
if (nextView != null) {
nextView.requestFocus()
keyEventListener?.invoke(Pair(event, true))
return true
}
}
when (keyCode) {
KeyEvent.KEYCODE_DPAD_CENTER -> {
if (act.currentFocus is SearchView || act.currentFocus is SearchView.SearchAutoComplete) {
UIHelper.showInputMethod(act.currentFocus?.findFocus())
}
}
}
}
//println("Keycode: $keyCode")
//showToast(
// this,
// "Got Keycode $keyCode | ${KeyEvent.keyCodeToString(keyCode)} \n ${event?.action}",
// Toast.LENGTH_LONG
//)
if (next != null && next != -1) {
val nextView = act.findViewById<View?>(next)
if (nextView != null) {
nextView.requestFocus()
keyEventListener?.invoke(Pair(event, true))
return true
}
}
if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER && (act.currentFocus is SearchView || act.currentFocus is SearchView.SearchAutoComplete)) {
UIHelper.showInputMethod(act.currentFocus?.findFocus())
}
//println("Keycode: $keyCode")
//showToast(
// this,
// "Got Keycode $keyCode | ${KeyEvent.keyCodeToString(keyCode)} \n ${event?.action}",
// Toast.LENGTH_LONG
//)
}
if (keyEventListener?.invoke(Pair(event, false)) == true) {

View file

@ -1,5 +1,7 @@
package com.lagradost.cloudstream3
import android.animation.ObjectAnimator
import android.animation.ValueAnimator
import android.content.ComponentName
import android.content.Context
import android.content.Intent
@ -11,12 +13,17 @@ import android.os.Bundle
import android.util.AttributeSet
import android.util.Log
import android.view.*
import android.view.animation.Animation
import android.view.animation.AnimationSet
import android.widget.LinearLayout
import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import androidx.annotation.IdRes
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.doOnLayout
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.ViewModelProvider
@ -28,12 +35,22 @@ import androidx.navigation.NavOptions
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.setupWithNavController
import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.transition.ChangeBounds
import androidx.transition.ChangeTransform
import androidx.transition.Scene
import androidx.transition.TransitionManager
import androidx.transition.TransitionManager.beginDelayedTransition
import androidx.transition.TransitionSet
import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.google.android.gms.cast.framework.*
import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.button.MaterialButton
import com.google.android.material.navigationrail.NavigationRailView
import com.google.android.material.snackbar.Snackbar
import com.jaredrummler.android.colorpicker.ColorPickerDialogListener
@ -119,6 +136,7 @@ import com.lagradost.nicehttp.ResponseParser
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import java.io.File
import java.lang.ref.WeakReference
import java.net.URI
import java.net.URLDecoder
import java.nio.charset.Charset
@ -553,7 +571,6 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
}
}
override fun dispatchKeyEvent(event: KeyEvent?): Boolean {
CommonActivity.dispatchKeyEvent(this, event)?.let {
return it
@ -728,6 +745,68 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
}
var binding: ActivityMainBinding? = null
var focusOutline: WeakReference<View> = WeakReference(null)
var lastFocus: WeakReference<View> = WeakReference(null)
val layoutListener: View.OnLayoutChangeListener =
View.OnLayoutChangeListener { v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom ->
updateFocusView(
v
)
}
private fun updateFocusView(newFocus: View?) {
val focusOutline = focusOutline.get() ?: return
//lastFocus.get()?.removeOnLayoutChangeListener(layoutListener)
val wasGone = focusOutline.isGone
focusOutline.isVisible =
newFocus != null && newFocus.measuredHeight > 0 && newFocus.measuredWidth > 0 && newFocus.isVisible && newFocus !is MaterialButton
if (newFocus != null) {
lastFocus = WeakReference(newFocus)
val out = IntArray(2)
newFocus.getLocationInWindow(out)
val (x, y) = out
/*(newFocus.parent as? RecyclerView)?.let { recycle ->
println("PARET IS RECYLE")
val position = recycle.getChildAdapterPosition(newFocus)
recycle.scrollToPosition(position)
(recycle.layoutManager as? GridLayoutManager)?.let {
if(it.orientation == LinearLayout.HORIZONTAL) {
println("SCROLL")
}
}
}*/
// newFocus.addOnLayoutChangeListener(layoutListener)
// val set = AnimationSet(true)
if(!wasGone) {
(focusOutline.parent as? ViewGroup)?.let {
TransitionManager.endTransitions(it)
TransitionManager.beginDelayedTransition(
it,
TransitionSet().addTransition(ChangeBounds())
.addTransition(ChangeTransform())
.setDuration(100)
)
}
}
// ObjectAnimator.ofFloat(focusOutline, "translationX",focusOutline.translationX, x.toFloat()
focusOutline.layoutParams = focusOutline.layoutParams?.apply {
width = newFocus.measuredWidth
height = newFocus.measuredHeight
}
focusOutline.translationX = x.toFloat()
focusOutline.translationY = y.toFloat()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
app.initClient(this)
@ -763,12 +842,12 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
// backup when we update the app, I don't trust myself to not boot lock users, might want to make this a setting?
try {
val appVer = BuildConfig.VERSION_NAME
val lastAppAutoBackup : String = getKey("VERSION_NAME") ?: ""
val lastAppAutoBackup: String = getKey("VERSION_NAME") ?: ""
if (appVer != lastAppAutoBackup) {
setKey("VERSION_NAME", BuildConfig.VERSION_NAME)
backup()
}
} catch (t : Throwable) {
} catch (t: Throwable) {
logError(t)
}
@ -777,6 +856,15 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
if (isTvSettings()) {
val newLocalBinding = ActivityMainTvBinding.inflate(layoutInflater, null, false)
setContentView(newLocalBinding.root)
focusOutline = WeakReference(newLocalBinding.focusOutline)
newLocalBinding.root.viewTreeObserver.addOnGlobalFocusChangeListener { _, newFocus ->
// println("refocus $oldFocus -> $newFocus")
updateFocusView(newFocus)
}
newLocalBinding.root.viewTreeObserver.addOnScrollChangedListener {
updateFocusView(lastFocus.get())
}
ActivityMainBinding.bind(newLocalBinding.root) // this may crash
} else {
val newLocalBinding = ActivityMainBinding.inflate(layoutInflater, null, false)
@ -816,7 +904,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
if (PluginManager.checkSafeModeFile()) {
normalSafeApiCall {
showToast( R.string.safe_mode_file, Toast.LENGTH_LONG)
showToast(R.string.safe_mode_file, Toast.LENGTH_LONG)
}
} else if (lastError == null) {
ioSafe {

View file

@ -2,9 +2,11 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<stroke android:width="2dp"
android:color="?attr/white"/>
<corners
<!-- <corners
android:bottomLeftRadius="@dimen/rounded_image_radius"
android:bottomRightRadius="@dimen/rounded_image_radius"
android:topLeftRadius="@dimen/rounded_image_radius"
android:topRightRadius="@dimen/rounded_image_radius" />
-->
</shape>

View file

@ -1,5 +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:drawable="@drawable/outline"/> <!-- focused -->
<!--<item android:state_focused="true"
android:drawable="@drawable/outline"/>--> <!-- focused -->
</selector>

View file

@ -77,4 +77,21 @@
tools:ignore="FragmentTagUsage" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:focusable="false"
android:focusableInTouchMode="false"
android:clickable="false"
android:visibility="gone"
android:id="@+id/focus_outline"
android:src="@drawable/outline"
android:layout_width="100dp"
android:layout_height="100dp">
</ImageView>
</FrameLayout>
</FrameLayout>

View file

@ -35,11 +35,10 @@
<com.google.android.material.button.MaterialButton
android:id="@+id/home_preview_change_api"
style="@style/BlackButton"
style="@style/RegularButtonTV"
android:layout_width="wrap_content"
android:layout_gravity="top|start"
android:layout_marginStart="@dimen/navbar_width"
android:backgroundTint="@color/semiWhite"
android:minWidth="150dp" />
</FrameLayout>
@ -92,7 +91,7 @@
<com.google.android.material.button.MaterialButton
android:id="@+id/home_preview_play_btt"
style="@style/WhiteButton"
style="@style/RegularButtonTV"
android:layout_width="wrap_content"
android:layout_margin="0dp"
android:minWidth="150dp"
@ -105,7 +104,7 @@
<com.google.android.material.button.MaterialButton
android:id="@+id/home_preview_info_btt"
style="@style/BlackButton"
style="@style/RegularButtonTV"
android:layout_width="wrap_content"
android:minWidth="150dp"

View file

@ -85,7 +85,8 @@
<style name="ChipFilled" parent="@style/Widget.Material3.Chip.Filter">
<item name="chipBackgroundColor">@color/chip_color</item>
<item name="chipStrokeColor">@color/white_transparent_toggle</item>
<!-- <item name="chipStrokeColor">@color/white_transparent_toggle</item>-->
<item name="chipStrokeColor">@color/transparent</item>
<item name="chipStrokeWidth">2dp</item>
<item name="textColor">@color/chip_color_text</item>
<item name="android:textColor">@color/chip_color_text</item>