Android實戰技巧: ListView之ContextMenu無法彈出

來源:互聯網
上載者:User
問題

Activity中使用了ListView作為布局.當每一清單項目中含有預設能擷取焦點的子View時有可能會對ListView的某些事件有影響:

1. OnItemClick
2. OnItemLongClick
3. ContextMenu

這三個事件都無法正確響應.

對於ContextMenu.首先要在onCreate中註冊Activity的ContextMenu到ListView上:

registerForContextMenu(mListView);

要在onDestroy中取消註冊:

unregisterForContextMenu(mListView);

一個簡單的解法就是在Adapter中構建列表中的每個Item時,把相應事件Click或者LongClick加到具體的item上面.但這樣的話,會造成邏輯十分混亂.而且點擊Item或者長按Item時不會有Focus的Selection.此現象十分奇怪,必定另有隱情!

Google了一下,果然StackOverflow上面有很多關於ListView 的ContextMenu的問題,首先要注意的是基本的用法,也就是上面提到的要registerForContextMenu.之後就是奇怪事件發生的地方了:

如果ListView的清單項目中含有預設就有Focus的子View(如Checkbox)時,就無法擷取ContextMenu.

這時就需要把Checkbox的Focus屬性改變:

android:focusable="false"

然後就可以了.

其實,ContextMenu也就是長按事件來的.所以不光是ContextMenu出不來,連onItemClick, onItemLongClick也都出不來!如果把Item中的Checkbox的android:focusable屬性設定成false,就可以解決這些問題.

但是,沒有人能解釋清楚為啥會醬紫!

看了ListView的原始碼,ListView並沒有控制Click和LongClick以及ContextMenu(ContextMenu也是由長按事件觸發的).這些事件是由它的父類AbsListView來管理的.
在AbsListView中有一個用於檢查LongClick的Runnable,它裡面有這樣一個判斷:

View v  = getChildAt(position);if (v != null && !v.hasFocusable()) {      .... do long click handling which will trigger context menu.}

也就是說每當長按一個項時,會檢查其hasFocusable()傳回值,返回false時才做長按的動作.其他地方比如onTouchEvent時也都會如此的檢查,發現hasFocusable()為true時就直接返回!這裡注意,檢查的是所點擊的清單項目,所以如果清單項目的布局不一樣,現象就有可能不一樣!
那麼View.hasFocusable(),當View的focusable為true時返回true,或者當其有子View的focusable為true時,就返回true.簡單講就是View本身focusable為true或者有子View的focusable為true時就返回true.
因為,ListItem裡面有CheckBox,它的focusable屬性預設就是true的.所以就不會有ContextMenu彈出來.如果把CheckBox的focusable屬性設定為false,就可以正常的彈出了.
可以還是沒弄明白為啥要醬紫設計?需要牛人來指點下!
擴充

目前來看預設就有focusable屬性的有Button, CompoundButton, SeekBar, EditText,ImageButton,AutoCompleteTextView,WebView,WebTextView和它們的子類(怎麼找出來了呢,到系統的style檔案frameworks/base/core/res/res/value/styles.xml裡面搜尋focusable屬性為true).所以理論上來講,如果把這些Widget放入ListView裡面時,ListView的OnItemClick,OnItemLongClick以及ContextMenu都不會有效果.解決辦法就是把它們的focusable屬性設為false.

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.