setDescendantFocusability,在父View和子View间处理焦点关系

android:descendantFocusability用法简析

    开发中很常见的一个问题,项目中的listview不仅仅是简单的文字,常常需要自己定义listview,自己的Adapter去继承BaseAdapter,在adapter中按照需求进行编写,问题就出现了,可能会发生点击每一个item的时候没有反应,无法获取的焦点。原因多半是由于在你自己定义的Item中存在诸如ImageButton,Button,CheckBox等子控件(也可以说是Button或者Checkable的子类控件),此时这些子控件会将焦点获取到,所以常常当点击item时变化的是子控件,item本身的点击没有响应。

    这时候就可以使用descendantFocusability来解决啦,API描述如下:

android: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会覆盖子类控件而直接获得焦点



*******************************************************************************************************

这个函数是在ViewGroup里定义的,主要用于控制child View获取焦点的能力,比如是否阻止child View获取焦点。

 

他有三个常量可供设置

 

  1. FOCUS_BEFORE_DESCENDANTS ViewGroup本身先对焦点进行处理,如果没有处理则分发给child View进行处理
  2. FOCUS_AFTER_DESCENDANTS 先分发给Child View进行处理,如果所有的Child View都没有处理,则自己再处理
  3. FOCUS_BLOCK_DESCENDANTS ViewGroup本身进行处理,不管是否处理成功,都不会分发给ChildView进行处理

我们看下这个方法的实现
Setdescendantfocusability(int focusability)代码   收藏代码
  1. public void setDescendantFocusability(int focusability) {  
  2.         switch (focusability) {  
  3.             case FOCUS_BEFORE_DESCENDANTS:  
  4.             case FOCUS_AFTER_DESCENDANTS:  
  5.             case FOCUS_BLOCK_DESCENDANTS:  
  6.                 break;  
  7.             default:  
  8.                 throw new IllegalArgumentException("must be one of FOCUS_BEFORE_DESCENDANTS, "  
  9.                         + "FOCUS_AFTER_DESCENDANTS, FOCUS_BLOCK_DESCENDANTS");  
  10.         }  
  11.         mGroupFlags &= ~FLAG_MASK_FOCUSABILITY;  
  12.         mGroupFlags |= (focusability & FLAG_MASK_FOCUSABILITY);  
  13.     }  
 

 

可以看到,只有这三个常量可以设置,不是这三个常量会抛出异常的。

 

 

设置后,会在requestFocus(int direction, Rect previouslyFocusedRect) 方法里根据设置进行相应的处理。来看下实现

 

Requestfocus(int direction, rect previouslyfocusedrect)代码   收藏代码
  1. public boolean requestFocus(int direction, Rect previouslyFocusedRect) {  
  2.         if (DBG) {  
  3.             System.out.println(this + " ViewGroup.requestFocus direction="  
  4.                     + direction);  
  5.         }  
  6.         int descendantFocusability = getDescendantFocusability();  
  7.   
  8.         switch (descendantFocusability) {  
  9.             case FOCUS_BLOCK_DESCENDANTS:  
  10.                 return super.requestFocus(direction, previouslyFocusedRect);  
  11.             case FOCUS_BEFORE_DESCENDANTS: {  
  12.                 final boolean took = super.requestFocus(direction, previouslyFocusedRect);  
  13.                 return took ? took : onRequestFocusInDescendants(direction, previouslyFocusedRect);  
  14.             }  
  15.             case FOCUS_AFTER_DESCENDANTS: {  
  16.                 final boolean took = onRequestFocusInDescendants(direction, previouslyFocusedRect);  
  17.                 return took ? took : super.requestFocus(direction, previouslyFocusedRect);  
  18.             }  
  19.             default:  
  20.                 throw new IllegalStateException("descendant focusability must be "  
  21.                         + "one of FOCUS_BEFORE_DESCENDANTS, FOCUS_AFTER_DESCENDANTS, FOCUS_BLOCK_DESCENDANTS "  
  22.                         + "but is " + descendantFocusability);  
  23.         }  
  24.     }  

 

通过这里的实现可以看到上面定义的三个常量设置的意思。。




-------------华丽的分割线---------------------------------------

增加xml中的配置方法,一劳永逸

adapter的item根布局添加属性  android:descenadantFocusability="blockDesceadant"

ImageButton / Button/ checkBox中添加android:focusability="false"

可以解决item不相应点击事件问题

你可能感兴趣的:(android,ListView)