我有一个布局,我想以编程方式在视图之间切换焦点。我碰巧正在实现将焦点作为视图组旋转的东西。我的布局包含3个元素:一个文本视图和2个按钮:
<?xml version="1.0" encoding="utf-8"?>
<AccessContainer2 xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".AccessActivity">
<TextView
android:id="@+id/text_hello_world"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Hello World!"
android:nextFocusForward="@id/button_option_1"
android:focusable="true"
android:focusableInTouchMode="true">
<requestFocus/>
</TextView>
<LinearLayout
android:id="@+id/buttons"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="center"
android:focusable="false"
android:focusableInTouchMode="false"
android:descendantFocusability="afterDescendants">
<Button
android:id="@+id/button_option_1"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="Option 1"
android:nextFocusForward="@id/button_option_2"
android:focusable="true"
android:focusableInTouchMode="true" />
<Button
android:id="@+id/button_option_2"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="Option 2"
android:nextFocusForward="@id/text_hello_world"
android:focusable="true"
android:focusableInTouchMode="true" />
</LinearLayout>
</AccessContainer2>
我已经尝试为3个可聚焦元素中的每一个定义“前向”焦点,例如文本视图,按钮1,按钮2并返回文本视图。
我的代码,在我的视图组中,impl看起来像:
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
final View currentFocus = getFocusedChild();
if (currentFocus == null) {
Log.w(TAG, "No current focus!");
} else {
Log.i(TAG, String.format("Currently focused child view ID: %s", getId(currentFocus)));
View newFocus = focusSearch(currentFocus, FOCUS_FORWARD);
Log.i(TAG, String.format("New child to focus view ID: %s", getId(newFocus)));
if (!newFocus.requestFocus()) {
Log.w(TAG, String.format("Failed to focus new child view ID: %s", getId(newFocus)));
}
}
return true;
}
所以,
但是,我得到了这个结果:
04-08 14:51:33.600 14232 14232 I AccessContainer2: Currently focused child view ID: com.clover.accesswork:id/text_hello_world
04-08 14:51:33.600 14232 14232 I AccessContainer2: New child to focus view ID: com.clover.accesswork:id/button_option_1
04-08 14:51:34.721 14232 14232 I AccessContainer2: Currently focused child view ID: com.clover.accesswork:id/buttons
04-08 14:51:34.724 14232 14232 I AccessContainer2: New child to focus view ID: com.clover.accesswork:id/text_hello_world
因此,在第一次触摸时,它会找到button_option_1作为下一个焦点,但是当我调用请求焦点时,它将视图的容器(按钮)设置为具有焦点...即使我明确地告诉它布局不可聚焦并且它应该优先关注其后代(尽管我认为线性布局不要求这样做,而只是尝试一下)。
有什么想法吗?
这是一个“ RTFM”错误。事实证明,getFocusedChild()
被记录为:
返回此视图的焦点子级(如果有)。 孩子可能有焦点或包含焦点。
因此,在这种情况下,它将返回包含焦点的视图,而不是包含焦点的孩子。我编写了此函数来获取实际上具有焦点的子视图:
private View getFocused(ViewGroup vg) {
View focused = vg.getFocusedChild();
if (focused == null) {
return null;
}
if (focused instanceof ViewGroup) {
// Figure out if a child of the view group has focus
// Recursion!
View v = getFocused((ViewGroup) focused);
if (v == null) {
// The view group itself actually has focus
return focused;
} else {
// A child of the view group had focus
return v;
}
}
// A non-view group child had focus
return focused;
}