Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android ListView事件的研究

android ListView事件的研究

編輯:關於Android編程

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);
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved