OnItemClickLIstener不起作用

来源:互联网 发布:hql 查第一条 mysql 编辑:程序博客网 时间:2024/02/24 04:29

listview在android开发中很地方都用到了,通常我们需要定制item里面的视图,就要重写adapter。而item中的控件根据需要来添加。但是如果出现了某些特定的item控件,就可能导致listview 的onItemClickListener不起作用。

    下面是一个范例,说明这种情况。

     首先还是先看代码:

  布局xml文件如下:

?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
   >
  
    <ListView
android:id="@+id/lv_lv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1.0"
android:dividerHeight="1px"
android:scrollbars="none"
/>
 
</LinearLayout>

item布局xml如下:
?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
View Code
<LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <ImageView
            android:id="@+id/iv_photo"
            android:layout_width="45dp"
            android:layout_height="45dp"
           />
        <TableLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_weight="1.0"
            android:gravity="center_vertical">
            <TableRow>
               <TextView
                   android:id="@+id/tv_name"
                   android:layout_width="match_parent"
                   android:layout_height="wrap_content"
                   android:layout_weight="1.0"
                   android:ellipsize="marquee"                   android:marqueeRepeatLimit="marquee_forever"
                   android:singleLine="true"
                   android:text="xxx"
                    />
            </TableRow>
            <TableRow>
               <TextView
                   android:id="@+id/tv_phoneNum"
                   android:layout_width="match_parent"
                   android:layout_height="wrap_content"
                   android:ellipsize="marquee"
                   android:marqueeRepeatLimit="marquee_forever"
                   android:singleLine="true"
                   android:text="xxx"
                 />
            </TableRow>
        </TableLayout>
        <LinearLayout
            android:layout_width="43dp"
            android:layout_height="match_parent"
            android:gravity="left|center_vertical">
            <ImageButton
               android:id="@+id/ib_call"
               android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:src="@drawable/ic_launcher"/>
        </LinearLayout>
    </LinearLayout>

注意里面有一个ImageButton。

在activity中设置listview的onItemClickListener,需要做的事情就是当点击item的时候出现log信息,代码如下:


?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
listView.setOnItemClickListener(newOnItemClickListener()
        {
            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                   int position, long id)
            {
                // TODO Auto-generated method stub
                Log.i("mm"," onItemClick ");
               
            }
           
        });


以及设置listview的onTouchListener,需要的事情只是当touch的时候MotionEvent的事件,代码如下:

?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
listView.setOnTouchListener(newOnTouchListener()
        {
           
            @Override
            public booleanonTouch(View v, MotionEvent event)
            {
                // TODO Auto-generated method stub
                if(event.getAction() == MotionEvent.ACTION_DOWN)
                {
                   Log.i("mm","MotionEvent.ACTION_DOWN");
               }
               else if(event.getAction() == MotionEvent.ACTION_UP)
               {
                   Log.i("mm","MotionEvent.ACTION_UP");
               }
               else if(event.getAction() == MotionEvent.ACTION_MOVE)
               {
                   Log.i("mm","MotionEvent.ACTION_MOVE");
               }
               
               return false;
            }
        });


在adapter中设置ImageButton的onClicklistener,需要做的事情只是打出log信息,代码如下:

?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
holder.iv_call.setOnClickListener(newOnClickListener()
         {
            
             @Override
             public void onClick(View v)
             {
                 // TODO Auto-generated method stub
                 Log.i("mm","holder.iv_call.setOnClickListener ");
             }
         });


好了,以上都做完了,接下来运行工程。出现界面以后,我们来使劲的点item位置(除了imageButton),

结果log中没有出现打印的

Log.i("mm", " onItemClick ");
接下来拖动item看看touch事件
打出log如下:

?
代码片段,双击复制
01
02
03
04
11-0708:42:27.793: I/mm(540): MotionEvent.ACTION_MOVE
11-0708:42:28.681: I/mm(540): MotionEvent.ACTION_MOVE
11-0708:42:28.832: I/mm(540): MotionEvent.ACTION_MOVE
11-0708:42:28.992: I/mm(540): MotionEvent.ACTION_UP


大家可以看到没有action_down事件,也就是没有了点击事件,一个完整的touch是down--move--move--up,而这里没有了,这是为什么呢?

再点击imagButton,看看打印信息:

?
代码片段,双击复制
01
11-0708:44:31.131: I/mm(540): holder.iv_call.setOnClickListener


出现了我们期望的打印信息。

    在这里总结一下上面问题出现背景,item中有ImageButton,其余和平常使用listview一样的,而点击了item时,onItemClickListener不起作用,onTouchListener没有了motionEvent.down事件,点击imagebutton有onclick事件。

    我们分析一下,当item出现了imageButton时,onItemClickListener不起作用,而在Touch中没有了down事件,首先说明onItemClickListener处理的和MotionEvent的down事件有关,其次最重要的是这个down事件去了哪里呢?

    因为当item中有Checkable类以及Button类控件的时候,item的焦点会被子项获得,此时这些子控件会将焦点获取到,所以常常当点击item时变化的是子控件,item本身的点击没有响应。从而导致onItemClickListener不起作用。

    已经得知了问题导致的原因就是因为item没有获得焦点,焦点被子项拿走了,那么怎么解决这类问题,处理的途径无非就是通过设置子项不能获得焦点,同时item要获得焦点。 

    这里采用的方法,要用到两个属性:

一:

?
代码片段,双击复制
01
android:focusable="false"

这个属性的具体介绍可以i看我上一篇文章,设置的目的在于使得某个控件不能获得焦点。
二:
?
代码片段,双击复制
01
android:descendantFocusability="blocksDescendants"

这个属性用来设置子项焦点的处理先后顺序。

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.

android:beforeFocusability      viewgroup在子项处理之前获得焦点android:afterFocusability            viewGroup在子项处理之后获得焦点android:blocksFocusability          viewGroup阻止子项获得焦点
上面就是说子项焦点能力,定义了viewgroup和它的子元素处理的关系,这关系是指当一个view在获得焦点的时候,值必须是下面的常量之一。

       那么,我们肯定imageButton不能获得焦点,因此添加ImageButton属性 focusable="false",同时我们希望item中子项不能获得焦点,所以要把给android:descendantFocusability="blocksDescendants"属性添加到imageButton的父元素即可,简单的做可以设置item的根节点上。

      以上作完后,我们在测试一下。

     点击item,出现以下log:

?
代码片段,双击复制
01
02
03
11-0709:48:19.671: I/mm(1077): MotionEvent.ACTION_DOWN
11-0709:48:19.751: I/mm(1077): MotionEvent.ACTION_UP
11-0709:48:19.952: I/mm(1077):  onItemClick

touch事件有了,ItemClick也有有了,

    再次imageButton,出现以下log:

?
代码片段,双击复制
01
11-0709:50:01.673: I/mm(1077): holder.iv_call.setOnClickListener


说明点击ImageBUtton也获得点击事件。   

    以上完美的解决问题了。

    总结:本次出现的onItemClickListener不能响应的原因是在item中有button类(子类)或者checkable类(子类)控件导致了item的焦点在子项的控件上,处理的办法就是将子项的控件焦点去掉,同时在item中xml设置阻止子项获得焦点的属性,即可解决尚需问题

   综述: 出现onItemClickListener不能响应,原因可能有多种,本人总结了有两种情况,一种是isEnable中返回值为false导致不能点击和选择,一种是因为item中有了checkable或者button类(子类)控件导致了item的焦点失去,从不能响应。因此需要仔细分析,问题导致的具体原因,才更好的解决问题。

    最后:感谢上一篇文章中给我给意见的同学。


欢迎大家访问我的博客:http://www.cnblogs.com/xilinch/archive/2012/11/07/2759265.html 欢迎转载,但请标明出处
原创粉丝点击