onItemClickListener不起作用解決辦法2(原創)


     寫這邊文章之前,猶豫再三,不知道會不會冒犯一位朋友,他給我之前的一篇文章提出的意見。但我聲明真心無意,只是想把問題拿出來分析一下,希望獲得理解。

     listview在android開發中很地方都用到了,通常我們需要定制item里面的視圖,就要重寫adapter。而item中的控件根據需要來添加。但是如果出現了某些特定的item控件,就可能導致listview 的onItemClickListener不起作用。

    下面是一個范例,說明這種情況。

     首先還是先看代碼:

  布局xml文件如下:

View Code

  item布局xml如下:

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

View Code
 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的事件,代碼如下:

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

View Code
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的焦點失去,從不能響應。因此需要仔細分析,問題導致的具體原因,才更好的解決問題。

    最后:感謝上一篇文章中給我給意見的同學。

   歡迎轉載,但請標明出處,謝謝

 

 




 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM