From 15333123cd298357baf85fa2c5f044ada60481d6 Mon Sep 17 00:00:00 2001 From: CranberrySoup <142951702+CranberrySoup@users.noreply.github.com> Date: Mon, 18 Sep 2023 21:22:39 +0000 Subject: [PATCH] TV UI fixes (#612) * TV UI fixes --- .../cloudstream3/ui/result/ActorAdaptor.kt | 26 +++++++++++--- .../ui/result/ResultFragmentTv.kt | 35 +++++++++++++------ .../ui/settings/SettingsFragment.kt | 5 +++ .../main/res/layout/fragment_search_tv.xml | 2 +- 4 files changed, 51 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ActorAdaptor.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ActorAdaptor.kt index 531cb5d2..7b743388 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ActorAdaptor.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ActorAdaptor.kt @@ -3,6 +3,8 @@ package com.lagradost.cloudstream3.ui.result import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.annotation.IdRes +import androidx.annotation.LayoutRes import androidx.core.view.isVisible import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView @@ -12,7 +14,10 @@ import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.databinding.CastItemBinding import com.lagradost.cloudstream3.utils.UIHelper.setImage -class ActorAdaptor(private val focusCallback : (View?) -> Unit = {}) : RecyclerView.Adapter() { +class ActorAdaptor( + private var nextFocusUpId: Int? = null, + private val focusCallback: (View?) -> Unit = {} +) : RecyclerView.Adapter() { data class ActorMetaData( var isInverted: Boolean, val actor: ActorData, @@ -22,7 +27,8 @@ class ActorAdaptor(private val focusCallback : (View?) -> Unit = {}) : RecyclerV override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { 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( val binding: CastItemBinding, - private val focusCallback : (View?) -> Unit = {} + private val focusCallback: (View?) -> Unit = {} ) : RecyclerView.ViewHolder(binding.root) { @@ -78,8 +84,18 @@ class ActorAdaptor(private val focusCallback : (View?) -> Unit = {}) : RecyclerV 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 -> - if(hasFocus) { + if (hasFocus) { focusCallback(v) } } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragmentTv.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragmentTv.kt index c40d995b..4503cb88 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragmentTv.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragmentTv.kt @@ -114,10 +114,20 @@ class ResultFragmentTv : Fragment() { } } - private fun hasNoFocus(): Boolean { - val focus = activity?.currentFocus - if (focus == null || !focus.isVisible) return true - return focus == binding?.resultRoot +// private fun hasNoFocus(): Boolean { +// val focus = activity?.currentFocus +// if (focus == null || !focus.isVisible) return true +// 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?, validApiName: String?) { @@ -413,7 +423,13 @@ class ResultFragmentTv : Fragment() { setHorizontal() } - resultCastItems.adapter = ActorAdaptor { + val aboveCast = listOf( + binding?.resultEpisodesShow, + binding?.resultBookmarkButton, + ).firstOrNull { + it?.isVisible == true + } + resultCastItems.adapter = ActorAdaptor(aboveCast?.id) { toggleEpisodes(false) } } @@ -454,9 +470,7 @@ class ResultFragmentTv : Fragment() { resultPlaySeries.isVisible = false resultResumeSeries.isVisible = true - if (hasNoFocus()) { - resultResumeSeries.requestFocus() - } + focusPlayButton() resultResumeSeries.text = if (resume.isMovie) context?.getString(R.string.play_movie_button) else context?.getNameFull( @@ -539,9 +553,7 @@ class ResultFragmentTv : Fragment() { ) return@setOnLongClickListener true } - if (hasNoFocus()) { - resultPlayMovie.requestFocus() - } + focusPlayButton() } } } @@ -663,6 +675,7 @@ class ResultFragmentTv : Fragment() { ) return@setOnLongClickListener true } + focusPlayButton() } /* diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsFragment.kt index e53fa91a..4895b0d2 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsFragment.kt @@ -205,6 +205,11 @@ class SettingsFragment : Fragment() { } } } + + // Default focus on TV + if (isTrueTv) { + settingsGeneral.requestFocus() + } } } } \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_search_tv.xml b/app/src/main/res/layout/fragment_search_tv.xml index 4c4af404..5fec8c6a 100644 --- a/app/src/main/res/layout/fragment_search_tv.xml +++ b/app/src/main/res/layout/fragment_search_tv.xml @@ -99,7 +99,7 @@ android:id="@+id/search_autofit_results" android:layout_width="match_parent" android:layout_height="match_parent" - + android:layout_marginStart="@dimen/navbar_width" android:background="?attr/primaryBlackBackground" android:clipToPadding="false" android:descendantFocusability="afterDescendants"