android ListView事件的研究

來源:互聯網
上載者:User

1. ListView的OnItemClickListener不被觸發的另外一種情況              如,在一個ItemView中,只有一個TextView位於最左側,他的右側是空白地區,沒有任何控制項,當點擊右側地區時,並不會觸發OnItemClickListener,當點擊TextView所在的地區時,就能觸發這個事件。   看看這個事件的執行流程          右側空白的部分沒有View控制項,也就是說雖然用手指點擊了這一部分,但是沒有view擷取焦點,Android的事件觸發是從頂層view一層層往下尋找的,如果有view擷取焦點,就交給這個view處理,如果沒有,就交給activity處理。   click事件與touch事件的傳播方式是不同的   給ListView同時添加對touch和itemClick的監聽事件,他們的觸發順序是:   actionDown--------》action up---------》onItemClick   他們的執行流程為:   先按照touch事件的處理流程進行,然後在進行click事件的處理,這就說明,當使用者按下螢幕,產生了兩個事件,一個是touch事件,一個是click事件,添加到主線程的隊列中。       使用者手指觸控螢幕幕,滾動ListView,看起來也進行了click操作,但是結果是,只觸發了touch事件,沒有觸發click事件。       2. ListView 擷取焦點和ItemView擷取焦點之間的關係   2.1 ListView不擷取焦點,ItemView能擷取焦點嗎?   通過設定ItemView的android:focusable="true"    android:focusableInTouchMode="true"屬性,可以使ItemView在Touch mode 下擷取焦點,預設情況下,Touch mode下ItemView,menu等等控制項都是不能擷取焦點的。只有ListView擷取了焦點之後,ItemView才能擷取焦點。       實驗一:   設定ListView的focusable屬性為true,ItemView的android:focusable="true"   android:focusableInTouchMode="true",自訂touch事件監聽器,重寫onTouch方法   public boolean onTouch(View v, MotionEvent event) {             switch (event.getAction()) {             case MotionEvent.ACTION_DOWN:                 //clear();                 int x = (int) event.getX();                 int y = (int) event.getY();                 int position = mListView.pointToPosition(x, y);                 int firstVisiblePosition = mListView.getFirstVisiblePosition();                 view = mListView.getChildAt(position-firstVisiblePosition);                 if(view==null) return false;                 if(view.isFocusable()){                     Log.i(tag, "ItemView is focusable ");                 }                 if(view.isFocusableInTouchMode()){                     Log.i(tag, "ItemView is focusable in touchMode");                 }                 if(view.isInTouchMode()){                     Log.i(tag, "device is in touch mode.");                 }                 if(mListView.isFocusable()){                     Log.i(tag, "mListView is focusable ");                 }                 if(mListView.isFocusableInTouchMode()){                     Log.i(tag, "mListView isFocusableInTouchMode in touchMode");                 }                                 if(view.isFocused()){                     Log.i(tag, "ItemView have get focus ");                 }                 if(mListView.isFocused()){                     Log.i(tag, "mListView have get focus ");                 }                 if(view.isPressed()){                     Log.i(tag, "ItemView have get pressed ");                 }                 break;             case MotionEvent.ACTION_UP:                 if(view==null) return false;                 Log.i(tag, "OnTouchListener: up is working ");                 if(view.isFocused()){                     Log.i(tag, "ItemView have get focus ");                 }                 break;             default:                 break;             }             return false;         }   列印結果為:   ItemView is focusable ItemView is focusable in touchMode device is in touch mode. mListView is focusable mListView isFocusableInTouchMode in touchMode mListView have get focus OnTouchListener: up is working   當使用者觸控螢幕幕的時候,觸發了touch事件,但是只有ListView擷取了焦點,itemView卻沒有獲得焦點,說明itemView在預設狀態下,即時設定了能擷取焦點,能在touchmode下擷取焦點,實際上也是不能的   而ListView的focusable屬性即時不設為true,也是能夠擷取焦點的,那麼如何讓ItemView擷取焦點呢,有兩個方法,一個是View類的requestFocus()方法,一個是ListView的requestChildFocus(child, focused)方法,還有就是requestFocusFromTouch()方法,該方法是View類的方法,ListView繼承了該方法。   我們讓itemView調用requestFocus()方法或者requestFocusFromTouch()方法,這時itemView擷取了焦點,但是ListView沒有擷取焦點,這說明一個視圖中只能有一個view擷取焦點。   去掉itemView的android:focusableInTouchMode="true"屬性,調用requestFocusFromTouch()方法,可以強制使itemViw擷取焦點。ListView依舊沒有擷取焦點。       總結:   1. 當使用導航鍵上下左右滾動時,android架構會自動讓view擷取焦點(擷取焦點後,就會高亮顯示),然而當使用者用手觸控螢幕幕的時候,就不需要讓view自動擷取焦點了,也就是說,當使用者點擊了螢幕上的某個控制項時,該控制項就沒有必要自動擷取焦點了,因為使用者知道自己操作的是哪個控制項,當使用者觸摸手機螢幕,就會進入touch mode模式。   2. 在touch mode 模式下,有些控制項是不會自動擷取焦點的,但是還有些控制項會,通過isFocusableInTouchMode()可以知道該控制項在該touch模式下能否獲得焦點,TextView是預設不能獲得焦點的,ListView預設能夠獲得焦點,EditText等文字編輯類控制項都可以。通過設定android:focusableInTouchMode="true"貌似可以使view控制項擷取焦點,但是實際上並不會是veiw控制項擷取焦點,還需要手動調用requestFocusFromTouch()方法或者requestFocus()方法才能真正擷取焦點。這裡推薦使用requestFocusFromTouch()方法,即時不用設定android:focusableInTouchMode="true",也能強制使控制項擷取焦點。   3. 擷取ListView中有那個控制項擷取了焦點的方法                   mListView.findFocus();                 mListView.getFocusedChild();       4. 通過ListView的setItemsCanFocus(true)方法並不可以使ItemView在touch mode下可以擷取焦點,他只是表明在由ListAdapter建立的視圖中,可包含能獲得焦點的項目。   滾動事件發生在touch事件的後面,這種說法是不對的,通過實驗可以得到onScroll方法的執行是在touch事件之前的,並且每一次觸控螢幕幕,先觸發這個方法,然後才觸發touch事件,此外,當我們第一次進入列表介面時,onScroll方法也多次被調用,第一次是在執行onCreate方法時被調用,這事還沒有產生介面,所以visibleItemCount參數為0,然後的幾次調用就有了介面了,visibleItemCount也被賦予介面上顯示的item的個數,顯示不全的也算。差不多有兩次,這兩次的調用也是不一樣的,看看這三次調用這個方法的不同           當用手觸控螢幕幕上的某一項時,也會首先觸發這個方法,然後才是touch事件          通過重寫onTouch方法,可以實現當使用者觸控螢幕幕的時候,itemView擷取焦點,並且變色,但是出現了兩個問題:   1. 如果ListView可以顯示多頁,可以看到每頁上又有一個ItemViw擷取了焦點,不知道為什嗎?   推測:Adapter中getView方法的第二個蠶食convertView是複用的,估計是產生新的頁面的時候覆用了擷取焦點的veiw,這裡還要看源碼       2. 當滾動到非第一頁的時候,觸發螢幕,並不能使觸發點所在的ItemView擷取焦點?   ListView的getChildAt(int index)方法的參數index,與Adapter的getView方法的第一個參數position是不一樣的,每個介面顯示幾個item,就建立從0到介面顯示個數的索引,比如一個螢幕上顯示8條記錄,那麼索引就是   0---7,翻頁了,仍然會建立類似的索引,因此應該計算出觸發點的item在螢幕上的索引。   int x = (int) event.getX(); int y = (int) event.getY(); int position = mListView.pointToPosition(x, y); int firstVisiblePosition = mListView.getFirstVisiblePosition(); view = mListView.getChildAt(position-firstVisiblePosition);

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.