禁用对片段的关注
Disable focus on fragment
我正在做TV平台的应用,使用RCU做导航
我有一个用例,我有两个片段,一个在另一个片段之上,同时在屏幕上可见。
有没有办法禁用下面的聚焦片段?
片段视图上的 setFocusable(false) 不起作用,我能够聚焦下面片段中的元素。
提前致谢。
最后我想到的解决办法是:
为片段添加了自定义生命周期侦听器,即:onFragmentResume 和 onFragmentPause 事件,我当我需要 show/hide 或在片段之间切换时手动调用。
@Override
public void onFragmentResume() {
//Enable focus
if (getView() != null) {
//Enable focus
setEnableView((ViewGroup) view, true);
//Clear focusable elements
focusableViews.clear();
}
//Restore previous focus
if (previousFocus != null) {
previousFocus.requestFocus();
}
}
@Override
public void onFragmentPause() {
//Disable focus and store previously focused
if (getView() != null) {
//Store last focused element
previousFocus = getView().findFocus();
//Clear current focus
getView().clearFocus();
//Disable focus
setEnableView((ViewGroup) view, false);
}
}
/**
* Find focusable elements in view hierarchy
*
* @param viewGroup view
*/
private void findFocusableViews(ViewGroup viewGroup) {
int childCount = viewGroup.getChildCount();
for (int i = 0; i < childCount; i++) {
View view = viewGroup.getChildAt(i);
if (view.isFocusable()) {
if (!focusableViews.contains(view)) {
focusableViews.add(view);
}
}
if (view instanceof ViewGroup) {
findFocusableViews((ViewGroup) view);
}
}
}
/**
* Enable view
*
* @param viewGroup
* @param isEnabled
*/
private void setEnableView(ViewGroup viewGroup, boolean isEnabled) {
//Find focusable elements
findFocusableViews(viewGroup);
for (View view : focusableViews) {
view.setEnabled(isEnabled);
view.setFocusable(isEnabled);
}
}
我解决了这个问题,为片段布局的父 ViewGroup
创建自定义 class。在您的自定义 ViewGroup 中,您可以覆盖方法
focusSearch(focused: View?, direction: Int)
添加此逻辑:
override fun focusSearch(focused: View?, direction: Int): View? {
val focusSearch = super.focusSearch(focused, direction)
if (direction == View.FOCUS_DOWN) when (focused?.id) {
R.id.some_view_that_has_focus -> return new_view_focus
}
if (findViewById<View>(focusSearch.id) == null) {//the view found is not part of this parent return null
return null
}
return focusSearch
}
当新的焦点视图不属于此 parent
时比 return null。当无法访问其他一些视图焦点时,我会在 when
个案例中手动管理它。
我遇到了同样的问题,接受的答案对我有用。
这是我目前的实现版本(可以改进):
abstract class BaseFragment<....> : Fragment() {
private val screenFocusHelper = ScreenFocusHelper()
fun enableFocus() {
if (view != null) {
// Enable focus
screenFocusHelper.setEnableView(view as ViewGroup, true)
// Clear focusable elements
screenFocusHelper.focusableViews.clear()
}
childFragmentManager.fragments.forEach {
if (it is BaseFragment<*, *>) {
it.enableFocus()
}
}
}
fun disableFocus() {
if (view != null) {
// Store last focused element
screenFocusHelper.previousFocus = view?.findFocus()
// Clear current focus
view!!.clearFocus()
// Disable focus
screenFocusHelper.setEnableView(view as ViewGroup, false)
}
childFragmentManager.fragments.forEach {
if (it is BaseFragment<*, *>) {
it.disableFocus()
}
}
}
}
class ScreenFocusHelper {
var previousFocus: View? = null
val focusableViews: MutableList<View> = mutableListOf()
fun setEnableView(viewGroup: ViewGroup, isEnabled: Boolean) {
findFocusableViews(viewGroup)
for (view in focusableViews) {
view.isEnabled = isEnabled
view.isFocusable = isEnabled
}
}
private fun findFocusableViews(viewGroup: ViewGroup) {
val childCount = viewGroup.childCount
for (i in 0 until childCount) {
val view = viewGroup.getChildAt(i)
if (view.isFocusable) {
if (!focusableViews.contains(view)) {
focusableViews += view
}
}
if (view is ViewGroup) {
findFocusableViews(view)
}
}
}
}
我正在做TV平台的应用,使用RCU做导航
我有一个用例,我有两个片段,一个在另一个片段之上,同时在屏幕上可见。
有没有办法禁用下面的聚焦片段? 片段视图上的 setFocusable(false) 不起作用,我能够聚焦下面片段中的元素。
提前致谢。
最后我想到的解决办法是:
为片段添加了自定义生命周期侦听器,即:onFragmentResume 和 onFragmentPause 事件,我当我需要 show/hide 或在片段之间切换时手动调用。
@Override
public void onFragmentResume() {
//Enable focus
if (getView() != null) {
//Enable focus
setEnableView((ViewGroup) view, true);
//Clear focusable elements
focusableViews.clear();
}
//Restore previous focus
if (previousFocus != null) {
previousFocus.requestFocus();
}
}
@Override
public void onFragmentPause() {
//Disable focus and store previously focused
if (getView() != null) {
//Store last focused element
previousFocus = getView().findFocus();
//Clear current focus
getView().clearFocus();
//Disable focus
setEnableView((ViewGroup) view, false);
}
}
/**
* Find focusable elements in view hierarchy
*
* @param viewGroup view
*/
private void findFocusableViews(ViewGroup viewGroup) {
int childCount = viewGroup.getChildCount();
for (int i = 0; i < childCount; i++) {
View view = viewGroup.getChildAt(i);
if (view.isFocusable()) {
if (!focusableViews.contains(view)) {
focusableViews.add(view);
}
}
if (view instanceof ViewGroup) {
findFocusableViews((ViewGroup) view);
}
}
}
/**
* Enable view
*
* @param viewGroup
* @param isEnabled
*/
private void setEnableView(ViewGroup viewGroup, boolean isEnabled) {
//Find focusable elements
findFocusableViews(viewGroup);
for (View view : focusableViews) {
view.setEnabled(isEnabled);
view.setFocusable(isEnabled);
}
}
我解决了这个问题,为片段布局的父 ViewGroup
创建自定义 class。在您的自定义 ViewGroup 中,您可以覆盖方法
focusSearch(focused: View?, direction: Int)
添加此逻辑:
override fun focusSearch(focused: View?, direction: Int): View? {
val focusSearch = super.focusSearch(focused, direction)
if (direction == View.FOCUS_DOWN) when (focused?.id) {
R.id.some_view_that_has_focus -> return new_view_focus
}
if (findViewById<View>(focusSearch.id) == null) {//the view found is not part of this parent return null
return null
}
return focusSearch
}
当新的焦点视图不属于此 parent
时比 return null。当无法访问其他一些视图焦点时,我会在 when
个案例中手动管理它。
我遇到了同样的问题,接受的答案对我有用。
这是我目前的实现版本(可以改进):
abstract class BaseFragment<....> : Fragment() {
private val screenFocusHelper = ScreenFocusHelper()
fun enableFocus() {
if (view != null) {
// Enable focus
screenFocusHelper.setEnableView(view as ViewGroup, true)
// Clear focusable elements
screenFocusHelper.focusableViews.clear()
}
childFragmentManager.fragments.forEach {
if (it is BaseFragment<*, *>) {
it.enableFocus()
}
}
}
fun disableFocus() {
if (view != null) {
// Store last focused element
screenFocusHelper.previousFocus = view?.findFocus()
// Clear current focus
view!!.clearFocus()
// Disable focus
screenFocusHelper.setEnableView(view as ViewGroup, false)
}
childFragmentManager.fragments.forEach {
if (it is BaseFragment<*, *>) {
it.disableFocus()
}
}
}
}
class ScreenFocusHelper {
var previousFocus: View? = null
val focusableViews: MutableList<View> = mutableListOf()
fun setEnableView(viewGroup: ViewGroup, isEnabled: Boolean) {
findFocusableViews(viewGroup)
for (view in focusableViews) {
view.isEnabled = isEnabled
view.isFocusable = isEnabled
}
}
private fun findFocusableViews(viewGroup: ViewGroup) {
val childCount = viewGroup.childCount
for (i in 0 until childCount) {
val view = viewGroup.getChildAt(i)
if (view.isFocusable) {
if (!focusableViews.contains(view)) {
focusableViews += view
}
}
if (view is ViewGroup) {
findFocusableViews(view)
}
}
}
}