寫這邊文章之前,猶豫再三,不知道會不會冒犯一位朋友,他給我之前的一篇文章提出的意見。但我聲明真心無意,只是想把問題拿出來分析一下,希望獲得理解。
listview在android開發中很地方都用到了,通常我們需要定制item里面的視圖,就要重寫adapter。而item中的控件根據需要來添加。但是如果出現了某些特定的item控件,就可能導致listview 的onItemClickListener不起作用。
下面是一個范例,說明這種情況。
首先還是先看代碼:
布局xml文件如下:

item布局xml如下:

<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信息,代碼如下:

listView.setOnItemClickListener(new OnItemClickListener() { @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的事件,代碼如下:

listView.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(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信息,代碼如下:

holder.iv_call.setOnClickListener(new OnClickListener() { @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如下:
11-07 08:42:27.793: I/mm(540): MotionEvent.ACTION_MOVE 11-07 08:42:28.681: I/mm(540): MotionEvent.ACTION_MOVE 11-07 08:42:28.832: I/mm(540): MotionEvent.ACTION_MOVE 11-07 08:42:28.992: I/mm(540): MotionEvent.ACTION_UP
大家可以看到沒有action_down事件,也就是沒有了點擊事件,一個完整的touch是down--move--move--up,而這里沒有了,這是為什么呢?
再點擊imagButton,看看打印信息:
11-07 08:44:31.131: I/mm(540): holder.iv_call.setOnClickListener
出現了我們期望的打印信息。
在這里總結一下上面問題出現背景,item中有ImageButton,其余和平常使用listview一樣的.當點擊item時,onItemClickListener不起作用,ontouchListener中motionEvent.down消失了,事件只有點擊item中的imagButton起作用。
我們分析一下,當item出現了imageButton時,onItemClickListener不起作用,而在Touch中沒有了down事件,首先說明onItemClickListener處理的和MotionEvent的down事件有關,然后問題的關鍵是這個down事件去了哪里呢?
經過排查當item中有Checkable類以及Button類控件的時候,item的焦點會被子項獲得,此時這些子控件會將焦點獲取到,所以常常當點擊item時變化的是子控件,item本身的點擊沒有響應。從而導致onItemClickListener不起作用。
已經得知了問題導致的原因就是因為item沒有獲得焦點,焦點被子項拿走了,那么怎么解決這類問題?本人認為處理的途徑無非就是通過設置子項不能獲得焦點,同時item要獲得焦點。
這里采用的方法,要用到兩個屬性:
一:
android:focusable="false"
這個屬性的具體介紹可以i看我上一篇文章,設置的目的在於使得某個控件不能獲得焦點。
二:
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:
11-07 09:48:19.671: I/mm(1077): MotionEvent.ACTION_DOWN 11-07 09:48:19.751: I/mm(1077): MotionEvent.ACTION_UP 11-07 09:48:19.952: I/mm(1077): onItemClick
touch事件有了,ItemClick也有有了,
再次imageButton,出現以下log:
11-07 09: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的焦點失去,從不能響應。因此需要仔細分析,問題導致的具體原因,才更好的解決問題。
最后:感謝上一篇文章中給我給意見的同學。
歡迎轉載,但請標明出處,謝謝