最近项目中用到了gridview,顺带对gridview的item与子控件焦点问题进行小小的研究比较下;
项目需求:在simphone手持把枪上通过方向按钮实现gridview的菜单选择;
实现方法1:在子布局中写入button的background属性,在gridview中定义descendantFocusability为afterDescendants,让button优先获得焦点
ViewGroup.FOCUS_AFTER_DESCENDANTS:表示item的子控件优先于item获得焦点;
ViewGroup.FOCUS_BEFORE_DESCENDANTS:表示item优先于其子控件获得焦点
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<Button
android:id="@+id/btn"
style="@style/large_white_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bbuton_primary_rounded"
android:text="入库"/>
</LinearLayout>
<GridView
android:id="@+id/gridView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:numColumns="2"
android:horizontalSpacing="12dp"
android:verticalSpacing="12dp"
android:descendantFocusability="afterDescendants"
android:paddingTop="38dp"
android:paddingLeft="12dp"
android:paddingRight="12dp">
</GridView>
holder.btn.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if(hasFocus){
btnFocusChange.onFocusChange(pos,btn);
}
}
});
adapter.setOnBtnFocusChange(new GridViewAdapter.BtnFocusChange() {
@Override
public void onFocusChange(int pos, Button btn) {
Log.e("onFocusChange","" + pos);
btn.setSelected(true);
btn.setFocusable(true);
gridView.setSelection(pos);
}
});
结果:现象有改善,只是还是有问题:1.若有滚动,左右方向键需按两次才能切换菜单(原因可能与 gridView .setSelection(pos)有关,毕竟这句代码焦点是gridview的item项~而不是其子控件)2.若菜单在完全不可见的情况下,方向键无法选择得到,因此gridview也不可能
实现方法2:让gridview的item获得焦点,设置listSelector属性gridview_item_selector,item文件下设置android:descendantFocusability="blocksDescendants"
ListView默认情况
当item有焦点时,item上的button等子控件获取不到焦点;
当子控件有焦点时,item无焦点无法响应onItemClick事件
<GridView
android:id="@+id/gridView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:numColumns="2"
android:horizontalSpacing="12dp"
android:verticalSpacing="12dp"
android:paddingTop="38dp"
android:listSelector="@drawable/gridview_item_selector"
android:paddingLeft="12dp"
android:paddingRight="12dp">
</GridView>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:padding="1dp"
android:descendantFocusability="blocksDescendants">
<Button
android:id="@+id/btn"
style="@style/large_white_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bbuton_primary_rounded"
android:text="入库"
android:gravity="center"/>
</LinearLayout>
<?xmlversion="1.0"encoding="utf-8"?>
<selectorxmlns:android="http://schemas.android.com/apk/res/android">
<itemandroid:state_selected="true">
<shapeandroid:shape="rectangle">
<solidandroid:color="#FFE1E1E1"/>
<strokeandroid:width="1dp"android:color="@color/black"/>
<cornersandroid:radius="@dimen/radius"/>
</shape>
</item>
<itemandroid:state_pressed="true">
<shapeandroid:shape="rectangle">
<solidandroid:color="#FFE1E1E1"/>
<strokeandroid:width="1dp"android:color="@color/black"/>
<cornersandroid:radius="@dimen/radius"/>
</shape>
</item>
<itemandroid:state_focused="true">
<shape>
<solidandroid:color="#FFE1E1E1"/>
<strokeandroid:width="1dp"android:color="@color/black"/>
<cornersandroid:radius="@dimen/radius"/>
</shape>
</item>
<itemandroid:state_active="true">
<shape>
<solidandroid:color="#FFE1E1E1"/>
</shape>
</item>
<item>
<shapeandroid:shape="rectangle">
<solidandroid:color="@color/transparent"/>
</shape>
</item>
</selector>
结果:基本实现用方向键选取菜单时,gridview会随选择滚动,点击OK键时,能响应gridView.setOnItemClickListener(this)事件,但是此时发现触屏下,不用方向键手动点击触发菜单时,没响应(原因:button抢去了gridview的item点击事件)<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:padding="1dp"
android:descendantFocusability="blocksDescendants">
<TextView
android:id="@+id/btn"
style="@style/large_white_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bbuton_primary_rounded"
android:text="入库"
android:gravity="center"/>
</LinearLayout>
综上所述,选对实现方法是可以事半功倍的,若是一开始就用方法2,也就不用纠结耗费半天时间;写出来与大家分享,免得像我一样绕弯。还有最近刚好做到原因单选,本想用radiobutton实现,现在好像也可用gridview试试:)