防止Recyclerview失去焦点

问题描述 投票:0回答:3

我正在开发这个Android TV应用程序,该应用程序的一项活动包含一些按钮。单击按钮后,将填充RecyclerView(在同一活动中)并自动聚焦。

问题是当使用DPAD朝按钮方向导航时,RecyclerView失去了对按钮的关注。我想防止这种行为,即防止RecyclerView失去对活动的任何关注。以后,选择另一个按钮的唯一方法是单击后退按钮,我可以做到,没问题。

这是我尝试过的,但是没有起作用:

<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()
  }

以第二种方式,除非我在RecyclerView中使用android:descendantFocusability="blocksDescendants",否则从不调用FocusChangeListener,但这会阻止RecyclerView的项被聚焦。

android android-recyclerview android-tv
3个回答
0
投票

0
投票
在适配器类中添加以下方法,并定义每次单击时要执行的每个步骤。它正在我的应用程序中运行,希望对您有所帮助。

@Override public void onAttachedToRecyclerView(final RecyclerView recyclerView) { super.onAttachedToRecyclerView(recyclerView); recyclerView.setOnKeyListener(new View.OnKeyListener() { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { LinearLayoutManager lm = ((LinearLayoutManager) recyclerView.getLayoutManager()); if (event.getAction() == KeyEvent.ACTION_DOWN) { if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) { //return false or true; // whatever your case is } else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) { return false; } else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) { } else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) { } else if (keyCode == KeyEvent.KEYCODE_ENTER) { } else if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { } } return false; } }); recyclerView.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (hasFocus) { } else if (!hasFocus) { } } }); }


0
投票
在Android-TV上,管理Dpad导航的正确方法实际上是使用focusSearch方法。这是做什么的?

DPad导航实际上意味着焦点在某些视图之间改变。因此,当您按下Dpad-Right时,谁应该决定焦点应该放在哪里?包含所述Views的ViewGroup可以!

小背景:当一个视图不知道谁应该获得焦点时,它要求ViewGroup做出上述决定。因此,在大多数情况下,当您将焦点对准视图时按DpadRight时,

focusSearch在其容器上被调用的方向为= FOCUS_RIGHT(FOCUS_END)。

为您提供的解决方案非常简单。您有2种方法: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! else return null; // someone else will find the next focus } });

您可以创建一个自定义视图来扩展您用于recyclerview的任何容器,并执行相同的操作,这是我们使用带有顶部菜单及其下的各个片段的UI的一个更复杂的示例https://gist.github.com/RedLann/bfaffc06eb0f571234c6e46b697d633b
    注意:通常在xml中,我们在recyclerview android:descendantFocusability="afterDescendants"上使用注意:如此一来,当您第一次确定视图的焦点时,就会调用该视图的方法,即:
  1. protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect)

注意:如果使用这种方法,焦点管理变得非常容易,每个父视图(ViewGroup / Container)将为其直接子级管理焦点,如果不知道要做什么,可以将其委托给自己的父视图组返回super.focusSearch

© www.soinside.com 2019 - 2024. All rights reserved.