標籤:pulltorefresh multichoicemodeliste 長按刪除 全選 setchoicemode
本文為原創部落格,出自http://blog.csdn.net/minimicall
到今天為止,搜芽的賣家版本應該來說已經基本完成,攻堅克難的一路過來。速度也控制的比較好。
項目過程進度
從任務分配量上來看,基本還是我個人英雄主義。接下來這樣不行。但暫時也沒辦法,師弟還需要一個學習的過程。智質不錯,而且態度端正。相信搜芽買家,他就可以承擔更多的開發工作單位了。
接下來進入正題,說我們的PullToRefresh的點擊事件。其實,我是想做長按進入刪除的。
見。當然這個是我做出來之後的了,但做出來不容易。
先上
這個時候,使用者長按某個item,進入刪除選中模式。
這個時候ActionBar上的菜單發生了變化,變成了一個全選和刪除。
我們還可以點擊ActionBar全選來選擇所有Item
當然,你可以取消全選這個時候,你也可以單機某個Item取消該項。
選中了,然後按刪除菜單,就是那個垃圾桶表徵圖即可。就會刪除,刪除同步至伺服器。
問題出先了。發現點擊無效。。!
問題排查
網上很多方法。
第一個比較有用的是:http://www.tuicool.com/articles/ria6Zf
記錄下自己所犯的錯誤,在寫ListView的點擊事件時OnItemClickListener,onItemClick方法沒有執行,導致ListView條目點擊事件失效,檢查發現百度上有很多不同的答案,但究其本質都是ListView的Item搶佔焦點或者Item沒有擷取焦點甚至沒有綁定上OnItemClickListener監聽事件,而我所犯的錯誤是在ListView的Item布局中引入了一個Style,在Style中有一項<item name="android:clickable">true</item>,正是這一項導致所有Item都要搶佔焦點,所以ListView的點擊事件失效,在我去掉這一項之後ListView確實正常工作了。需要引以為戒的是,在androidl應用開發中,焦點沒有擷取或者其他組件搶佔焦點的事情經常發生,我們可以在代碼中,xml布局中,甚至Style中定義時候搶佔焦點,在一般情況下,這個設定並不會造成什麼異常,但我需要注意重要的組件在合適的時機必須拿到焦點,否則會產生意想不到的後果,比如我的ListView。一般組件擷取焦點可以使用一下方法:
[java] view plain copy
- View.setFocusable( true ),對應xml : android:focusable= "true" .
- View.setFocusableInTouchMode( true ),對應xml : android:focusableInTouchMode= "true" .
注意:這兩個屬性要同時使用。
兩者的意思是讓組件可以獲得焦點。不過有些區別,前者執行false條件後,在執行true,還是不能擷取焦點。後者執行上述過程,還是能擷取焦點。
當你加入上述代碼後,在建立activity時,調用對應view的requestFocus(),(requestFocus()需要在setContentView之後執行 )這樣就可以獲得焦點了。當editText失去焦點了,也就不會有軟鍵盤了
但針對ListView還可以使用 android:descendantFocusability 屬性, 下面我們來看一下 android:descendantFocusability用法簡析
以下摘自: http://www.cnblogs.com/eyu8874521/archive/2012/10/17/2727882.html
開發中很常見的一個問題,項目中的listview不僅僅是簡單的文字,常常需要自己定義listview,自己的Adapter去繼承BaseAdapter,在adapter中按照需求進行編寫,問題就出現了,可能會發生點擊每一個item的時候沒有反應,無法擷取的焦點。原因多半是由於在你自己定義的Item中存在諸如ImageButton,Button,CheckBox等子控制項(也可以說是Button或者Checkable的子類控制項),此時這些子控制項會將焦點擷取到,所以常常當點擊item時變化的是子控制項,item本身的點擊沒有響應。
這時候就可以使用descendantFocusability來解決啦,API描述如下:
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.
該屬性是當一個為view擷取焦點時,定義viewGroup和其子控制項兩者之間的關係。
屬性的值有三種:
beforeDescendants:viewgroup會優先其子類控制項而擷取到焦點
afterDescendants:viewgroup只有當其子類控制項不需要擷取焦點時才擷取焦點
blocksDescendants:viewgroup會覆蓋子類控制項而直接獲得焦點
通常我們用到的是第三種,即在Item布局的根布局加上android:descendantFocusability=”blocksDescendants”的屬性就好了,至此listview點擊的靈異事件告一段落。心得:遇到不會不懂的地方除了網上查詢資料之外,也可以多多去嘗試每種屬性的作用,多閱讀官方文檔(我始終覺得還是讀原文的比翻譯的理解的會更好)
第二個比較有意的是:
http://blog.csdn.net/kankankankan2222/article/details/7693190
如果ListView中的單個Item的view中存在checkbox,button等view,會導致ListView.setOnItemClickListener無效,
事件會被子View捕獲到,ListView無法捕獲處理該事件.
解決方案:
在checkbox、button對應的view處加android:focusable="false"
android:clickable="false"android:focusableInTouchMode="false"
其中focusable是關鍵
從OnClickListener調用getSelectedItemPosition(),Click 和selection 是不相關的,Selection是通過D-pad or trackball 來操作的,Click通常是點擊操作的。
我犯得錯是自己在getView裡面不小心設定了對Click的監聽導致的。已經被我注釋掉了
// private class ClickListner implements OnClickListener {// private int position;//// private ClickListner(int position) {// this.position = position;// }//// @Override// public void onClick(View v) {// Log.d(TAG,"xxxxxxxxxxx");// MCloth cloth = mCloths.get(position);// if (!isEnabled(position)) {// return;// }// Context context = v.getContext();// //DetailActivity.launch(context, movie, Referer.NEW_ARRIVIAL);// }// }接下來我講一下,如何?PullToRefresh來實現長按進入刪除選中模式。
長按進入刪除模式
首先,在需要初始化View各種監聽的地方,我們開一個函數。如下,相信大家都熟悉,
private void setupViews(View rootView) {mListView = (PullToRefreshListView) rootView.findViewById(R.id.cloths_lv);mListView.setMode(PullToRefreshBase.Mode.BOTH);((ViewGroup) mListView.getParent()).addView(mErrorView);mListView.setEmptyView(mErrorView);mClothManageAdapter = new ClothManageAdapter(getActivity(),getImageFetcher());mListView.setAdapter(mClothManageAdapter);((MainActivity) getActivity()).getIndicator().setOnTabSelectedListener(mTabSelectdListener);mProgressBar = (ProgressBar) rootView.findViewById(R.id.pb_progress);setListViewRefresh();setLongClickListener();}
我們把注意力放到setLongClickListener上,這個是我封的一個private方法,如下:
private void setLongClickListener() {Log.d(TAG, "setLongClick");mListView.getRefreshableView().setOnItemClickListener(mOnItemClickListener);//單擊事件的監聽mListView.getRefreshableView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);//選擇模式選為可多選mListView.getRefreshableView().setMultiChoiceModeListener(mMutilChoiceListener);//多選監聽}好,我們再進一步看單擊時間的監聽
private final OnItemClickListener mOnItemClickListener = new OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position,long id) {if (mActionMode == null) {//還沒有按長按的時候,走這裡。Log.d(TAG, "onItemClick,mActionMode is null");} else {//已經有了一次長按之後,進入了選擇模式,走這裡Log.d(TAG, "onItemClick,mActionMode is not null, select item "+ position + " to select");mListView.getRefreshableView().setItemChecked(position, true);}}};好,我們看我們很關鍵的多選監聽。直接上代碼
private final MultiChoiceModeListener mMutilChoiceListener = new MultiChoiceModeListener() {@Overridepublic boolean onCreateActionMode(ActionMode mode, Menu menu) {Log.d(TAG, "onCreateActionMode, mode:" + mode + ",menu:" + menu);mActionMode = mode;getActivity().getMenuInflater().inflate(R.menu.menu_favorite_delete, menu);//載入菜單到ActionBar中return true;}@Overridepublic boolean onPrepareActionMode(ActionMode mode, Menu menu) {return false;}@Overridepublic void onDestroyActionMode(ActionMode mode) {mActionMode = null;}@Overridepublic boolean onActionItemClicked(ActionMode mode, MenuItem item) {switch (item.getItemId()) {//菜單點擊事件case R.id.menu_delete: // 刪除Log.d(TAG,"delete menu");List<MCloth> deleted = new ArrayList<MCloth>();SparseBooleanArray checked = mListView.getRefreshableView().getCheckedItemPositions();for (int i = 0; i < checked.size(); i++) {Log.d(TAG, "get from Adapter("+checked.keyAt(i)+","+checked.valueAt(i)+")");if (checked.valueAt(i)) {deleted.add(mClothManageAdapter.getItem(checked.keyAt(i)));}}//for (MCloth cloth : deleted) {//if(cloth != null){////Log.d(TAG, "deleting the cloth id="+cloth.id+" in remote server now");// WEBInterface1.DelCloth(cloth.id);//}//}new DeleteClothTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, deleted);mClothManageAdapter.remove(deleted);mode.finish();loadData(true);break;case R.id.menu_selectall: // 全選if (mIsSelectAll) {item.setTitle("取消全選");mIsSelectAll = false;} else {item.setTitle("全選");mIsSelectAll = true;}for (int i = 0; i < mListView.getRefreshableView().getCount(); i++) {mListView.getRefreshableView().setItemChecked(i,!mIsSelectAll);}break;}return true;}@Overridepublic void onItemCheckedStateChanged(ActionMode mode, int position,long id, boolean checked) {setActionModeTitle(mode, mListView.getRefreshableView().getCheckedItemCount());}};private void setActionModeTitle(ActionMode mode, int count) {Log.d(TAG, "setActionModeTitile,mode:" + mode + ",count:" + count);mActionMode.setTitle("選中" + count + "個布料");}這樣
核心的代碼就是上面了,實現了長按刪除的,效果不錯吧。不懂的可以聯絡我。希望我們的搜芽產品能夠一天天的長成大樹。晚安。有想加入我們團隊的,也可以聯絡我。我會給你力所能及的協助,也期待大家的愉快合作。
Android開發之PullToRefresh的Click點擊事件的監聽實現長按刪除Item