tra*_*nho 19 android focus android-custom-view viewgroup android-view
假设我有一个可自由聚焦的自定义ViewGroup,并且有一些可以聚焦的子视图(Android机顶盒的自定义垂直菜单应该在远程控制器上作出反应).
每当自定义ViewGroup获得焦点时,我都需要将焦点传递给一些子视图.
我设置descendantFocusability为beforeDescendants并设置OnFocusChangeListener为自定义ViewGroup但OnFocusChangeListener.onFocusChanged()从未调用.它看起来像beforeDescendants我预期的那样不起作用.实际设置beforeDescendants工作与设置相同afterDescendants- 焦点由最近的子视图拍摄,自定义ViewGroup没有机会决定哪个子视图应该关注焦点.
我怎样才能达到理想的行为?在ViewGroups中处理焦点的最佳实践是什么?
深入研究Android资料后,我了解了如何将重点分配给ViewGroup的孩子。例如,我有ViewGroup几个EditText内部字段的自定义。当用户单击ViewGroup(在每个窗口之外EditText)时,我想将焦点分配到其中一个字段。
为此,我们需要将DescendantFocusability设置为FOCUS_AFTER_DESCENDANTS。这意味着我们可以在我们的自定义视图尝试聚焦之前处理焦点事件:
setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
Run Code Online (Sandbox Code Playgroud)
下一步是重写onRequestFocusInDescendants方法,将在设置自定义视图的requestFocusif标志之前调用该方法FOCUS_AFTER_DESCENDANTS。在这种方法中,我们可以请求子级焦点:
@Override
protected boolean onRequestFocusInDescendants(final int dir, final Rect rect) {
return getChildAt(this.target).requestFocus();
}
Run Code Online (Sandbox Code Playgroud)
使用此方法的重要一件事:如果返回true此处,则不会要求我们的自定义视图集中显示(仅使用FOCUS_AFTER_DESCENDANTS)。
通过这种方式,我们可以更改target字段以更改ViewGroup单击时将重点关注哪个孩子。
requestFocus方法ViewGroup。
小智 5
我有类似的问题。在我们的 Android TV 应用程序中,我们想要选择自定义菜单的最后一个焦点位置(它是自定义垂直 LinearLayout)。
你应该重写方法addFocusables(views: ArrayList<View>, direction: Int, focusableMode: Int)。当 ViewRootImpl 搜索所有可用的可聚焦视图时,会调用此方法。标志 FOCUS_AFTER_DESCENDANTS 和 FOCUS_BEFORE_DESCENDANTS 仅确定将父视图插入可聚焦视图的位置。如果是 FOCUS_BEFORE_DESCENDANTS,您的自定义视图将添加到您的子视图之前。如果是 FOCUS_AFTER_DESCENDANTS,您的自定义视图将添加到您的子视图之后。
覆盖的逻辑是仅在列表中添加您的自定义视图(当您之前没有焦点子视图时)。
override fun addFocusables(views: ArrayList<View>, direction: Int, focusableMode: Int) {
// if we did have focused child before, we must add only parent view
// otherwise our child already has focus, and we don't wont to change focus behavior
if (focusedChild == null) {
views.add(this)
} else {
super.addFocusables(views, direction, focusableMode)
}
}
Run Code Online (Sandbox Code Playgroud)
您还必须推翻,requestFocus(direction: Int, previouslyFocusedRect: Rect)因为您必须将注意力转移给您的孩子或决定您不能这样做。
override fun requestFocus(direction: Int, previouslyFocusedRect: Rect): Boolean =
getViewToFocus()?.requestFocus() ?: false
Run Code Online (Sandbox Code Playgroud)
在此示例中, getViewToFocus() 返回我想要聚焦的子项,如果我们没有任何子项,则返回 null
private fun getViewToFocus() =
when {
lastSelectedPos in 0..childCount -> getChildAt(lastSelectedPos)
isNotEmpty() -> getChildAt(0)
else -> null
}
Run Code Online (Sandbox Code Playgroud)
我在示例中使用 Kotlin,但您也可以使用 java。享受!
| 归档时间: |
|
| 查看次数: |
2196 次 |
| 最近记录: |