TV UI fixes (#612)

* TV UI fixes
This commit is contained in:
CranberrySoup 2023-09-18 21:22:39 +00:00 committed by GitHub
parent 2ae5b6cefb
commit 15333123cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 51 additions and 17 deletions

View File

@ -3,6 +3,8 @@ package com.lagradost.cloudstream3.ui.result
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 androidx.annotation.IdRes
import androidx.annotation.LayoutRes
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
@ -12,7 +14,10 @@ import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.databinding.CastItemBinding import com.lagradost.cloudstream3.databinding.CastItemBinding
import com.lagradost.cloudstream3.utils.UIHelper.setImage import com.lagradost.cloudstream3.utils.UIHelper.setImage
class ActorAdaptor(private val focusCallback : (View?) -> Unit = {}) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { class ActorAdaptor(
private var nextFocusUpId: Int? = null,
private val focusCallback: (View?) -> Unit = {}
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
data class ActorMetaData( data class ActorMetaData(
var isInverted: Boolean, var isInverted: Boolean,
val actor: ActorData, val actor: ActorData,
@ -22,7 +27,8 @@ class ActorAdaptor(private val focusCallback : (View?) -> Unit = {}) : RecyclerV
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return CardViewHolder( return CardViewHolder(
CastItemBinding.inflate(LayoutInflater.from(parent.context), parent, false), focusCallback CastItemBinding.inflate(LayoutInflater.from(parent.context), parent, false),
focusCallback
) )
} }
@ -64,10 +70,10 @@ class ActorAdaptor(private val focusCallback : (View?) -> Unit = {}) : RecyclerV
} }
} }
private class CardViewHolder private inner class CardViewHolder
constructor( constructor(
val binding: CastItemBinding, val binding: CastItemBinding,
private val focusCallback : (View?) -> Unit = {} private val focusCallback: (View?) -> Unit = {}
) : ) :
RecyclerView.ViewHolder(binding.root) { RecyclerView.ViewHolder(binding.root) {
@ -78,8 +84,18 @@ class ActorAdaptor(private val focusCallback : (View?) -> Unit = {}) : RecyclerV
Pair(actor.voiceActor?.image, actor.actor.image) Pair(actor.voiceActor?.image, actor.actor.image)
} }
// Fix tv focus escaping the recyclerview
if (position == 0) {
itemView.nextFocusLeftId = R.id.result_cast_items
} else if ((position - 1) == itemCount) {
itemView.nextFocusRightId = R.id.result_cast_items
}
nextFocusUpId?.let {
itemView.nextFocusUpId = it
}
itemView.setOnFocusChangeListener { v, hasFocus -> itemView.setOnFocusChangeListener { v, hasFocus ->
if(hasFocus) { if (hasFocus) {
focusCallback(v) focusCallback(v)
} }
} }

View File

@ -114,10 +114,20 @@ class ResultFragmentTv : Fragment() {
} }
} }
private fun hasNoFocus(): Boolean { // private fun hasNoFocus(): Boolean {
val focus = activity?.currentFocus // val focus = activity?.currentFocus
if (focus == null || !focus.isVisible) return true // if (focus == null || !focus.isVisible) return true
return focus == binding?.resultRoot // return focus == binding?.resultRoot
// }
/**
* Force focus any play button.
* Note that this will steal any focus if the episode loading is too slow (unlikely).
*/
private fun focusPlayButton() {
binding?.resultPlayMovie?.requestFocus()
binding?.resultPlaySeries?.requestFocus()
binding?.resultResumeSeries?.requestFocus()
} }
private fun setRecommendations(rec: List<SearchResponse>?, validApiName: String?) { private fun setRecommendations(rec: List<SearchResponse>?, validApiName: String?) {
@ -413,7 +423,13 @@ class ResultFragmentTv : Fragment() {
setHorizontal() setHorizontal()
} }
resultCastItems.adapter = ActorAdaptor { val aboveCast = listOf(
binding?.resultEpisodesShow,
binding?.resultBookmarkButton,
).firstOrNull {
it?.isVisible == true
}
resultCastItems.adapter = ActorAdaptor(aboveCast?.id) {
toggleEpisodes(false) toggleEpisodes(false)
} }
} }
@ -454,9 +470,7 @@ class ResultFragmentTv : Fragment() {
resultPlaySeries.isVisible = false resultPlaySeries.isVisible = false
resultResumeSeries.isVisible = true resultResumeSeries.isVisible = true
if (hasNoFocus()) { focusPlayButton()
resultResumeSeries.requestFocus()
}
resultResumeSeries.text = resultResumeSeries.text =
if (resume.isMovie) context?.getString(R.string.play_movie_button) else context?.getNameFull( if (resume.isMovie) context?.getString(R.string.play_movie_button) else context?.getNameFull(
@ -539,9 +553,7 @@ class ResultFragmentTv : Fragment() {
) )
return@setOnLongClickListener true return@setOnLongClickListener true
} }
if (hasNoFocus()) { focusPlayButton()
resultPlayMovie.requestFocus()
}
} }
} }
} }
@ -663,6 +675,7 @@ class ResultFragmentTv : Fragment() {
) )
return@setOnLongClickListener true return@setOnLongClickListener true
} }
focusPlayButton()
} }
/* /*

View File

@ -205,6 +205,11 @@ class SettingsFragment : Fragment() {
} }
} }
} }
// Default focus on TV
if (isTrueTv) {
settingsGeneral.requestFocus()
}
} }
} }
} }

View File

@ -99,7 +99,7 @@
android:id="@+id/search_autofit_results" android:id="@+id/search_autofit_results"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_marginStart="@dimen/navbar_width"
android:background="?attr/primaryBlackBackground" android:background="?attr/primaryBlackBackground"
android:clipToPadding="false" android:clipToPadding="false"
android:descendantFocusability="afterDescendants" android:descendantFocusability="afterDescendants"