我正在开发这个 android TV 应用程序,它有一个包含一些按钮的 Activity 。单击按钮后,RecyclerView(在同一个 Activity 中)被填充并自动聚焦。
问题是当使用 DPAD 向按钮方向导航时,RecyclerView 失去对按钮的焦点。我想防止这种行为,即防止 RecyclerView 失去对 Activity 的其他任何东西的关注。后来,选择另一个按钮的唯一方法是单击返回按钮,这个我可以做到,没问题。
这是我尝试过的,但没有奏效:
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/categories_rv"
android:layout_width="@dimen/categories_list_width"
android:layout_height="wrap_content"
android:focusable="true"
android:nextFocusForward="@id/categories_rv"
android:nextFocusUp="@id/categories_rv"
android:nextFocusRight="@id/categories_rv"
android:nextFocusLeft="@id/categories_rv"
android:nextFocusDown="@id/categories_rv"
android:focusableInTouchMode="true" />
和这个:
binding.categoriesRv.setOnFocusChangeListener { v, hasFocus ->
if (!hasFocus)
v.requestFocus()
}
在第二种方式中,除非我使用
android:descendantFocusability="blocksDescendants"
,否则永远不会调用 FocusChangeListener在 RecyclerView 中,但这会阻止 RecyclerView 的项目被聚焦。
最佳答案
首先,我在 AndroidTv 上工作了 3 年,与焦点管理作斗争,实际上很简单,问题是......没有文档!
在 Android-TV 上,管理 Dpad 导航的正确方法实际上是使用 focusSearch 方法。这是做什么的?
DPad 导航实际上意味着一些 View 之间的焦点变化。那么当你按下 Dpad-Right 时,谁来决定焦点应该在哪里呢?包含 View 的 ViewGroup(父级)可以!
一点背景知识:当 View 不知道谁应该获得焦点时,它会要求 ViewGroup 做出决定。因此,在大多数情况下,当您在关注 View 时按下 DpadRight, focusSearch 在其容器上被调用 方向 = FOCUS_RIGHT (FOCUS_END) 等等。
那么,您的解决方案非常简单。你有两种方法:
1. 将 Recyclerview 放在 BrowseFrameLayout 中,然后您可以执行以下操作
BrowseFrameLayout browseFrameLayout = view.findViewById(R.id.recyclerview_container);
RecyclerView recyclerView = view.findViewById(R.id.categories_rv);
theBrowseFrameLayout.setOnFocusSearchListener(new BrowseFrameLayout.OnFocusSearchListener() {
@Override
public View onFocusSearch(View focused, int direction) {
if (recyclerView.hasFocus())
return focused; // keep focus on recyclerview! DO NOT return recyclerview, but focused, which is a child of the recyclerview
else
return null; // someone else will find the next focus
}
});
注意:通常在我们在 recyclerview
android:descendantFocusability="afterDescendants"
上使用的 xml 中注意:为了让您知道 View 第一次获得焦点时,该 View 的一个方法被调用,即:
protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect)
注意:如果您使用这种方法,焦点管理变得非常容易,每个父 View (ViewGroup/Container)将为其直接 subview 管理焦点,当它不知道该做什么时,它可以委托(delegate)给它自己的父 View 组返回 super .focus搜索
关于android - 防止 Recyclerview 失去焦点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60223322/