当我们在一个ListView里面包含多个元素时,有时候我们对里面的每个元素要坐不同的点击事件处理,如下图:
这是android文字转语音输出设置,这里面包含3个元素,一个RadioButton,一个TextView,一个设置src为setting的icon,当我们用遥控或者键盘操作时,默认情况下里面的子元素是无法获取到焦点,因而无法响应相关点击事件。那我们就去查找一下源码,发现在TtsEnginePreference.java这个文件里面有加载布局:
public TtsEnginePreference(Context context, EngineInfo info, RadioButtonGroupState state,
PreferenceActivity prefActivity) {
super(context);
setLayoutResource(R.layout.preference_tts_engine);
mSharedState = state;
mPreferenceActivity = prefActivity;
mEngineInfo = info;
mPreventRadioButtonCallbacks = false;
setKey(mEngineInfo.name);
setTitle(mEngineInfo.label);
}
可以看到加载了preference_tts_engine这个布局。那我们在来看下preference_tts_engine这个布局的详细内容:
<!-- Copyright (C) 2011 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight"
android:gravity="center_vertical">
<LinearLayout
android:id="@+id/tts_engine_pref"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:clickable="true"
android:focusable="true"
android:background="?android:attr/selectableItemBackground">
<RadioButton
android:id="@+id/tts_engine_radiobutton"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginStart="10dip"
android:layout_marginEnd="4dip"
android:layout_gravity="center_vertical"
android:orientation="vertical"
android:clickable="true" />
<RelativeLayout
android:id="@+id/tts_engine_pref_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dip"
android:layout_marginEnd="6dip"
android:layout_marginTop="6dip"
android:layout_marginBottom="6dip"
android:layout_weight="1">
<TextView
android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceMedium"
android:ellipsize="marquee"
android:fadingEdge="horizontal"/>
<TextView
android:id="@android:id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@android:id/title"
android:layout_alignStart="@android:id/title"
android:visibility="gone"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textSize="13sp"
android:textColor="?android:attr/textColorSecondary"
android:maxLines="4" />
</RelativeLayout>
</LinearLayout>
<View
android:layout_width="2dip"
android:layout_height="match_parent"
android:layout_marginTop="5dip"
android:layout_marginBottom="5dip"
android:background="@android:drawable/divider_horizontal_dark" />
<ImageView
android:id="@+id/tts_engine_settings"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:paddingStart="15dip"
android:paddingEnd="?android:attr/scrollbarSize"
android:src="@drawable/ic_sysbar_quicksettings"
android:contentDescription="@string/tts_engine_settings_button"
android:layout_gravity="center"
android:clickable="true"
android:focusable="true"
android:background="?android:attr/selectableItemBackground" />
</LinearLayout>
顾名思义descendantFocusability是设置子元素的获取焦点相关的。根据官方文档:
Defines the relationship between the ViewGroup and its descendants when looking for a View to take focus.
Must be one of the following constant values.
该属性是当一个为view获取焦点时,定义viewGroup和其子控件两者之间的关系。
属性的值有三种:
● beforeDescendants:viewgroup会优先其子类控件而获取到焦点
● afterDescendants:viewgroup只有当其子类控件不需要获取焦点时才获取焦点
● blocksDescendants:viewgroup会覆盖子类控件而直接获得焦点
好了,分析到此,当我们把preference_tts_engine布局文件里面的LinearLayout添加属性android:descendantFocusability = “afterDescendants”时,每个子元素就可以独立获取焦点了。