将ListView choiceMode从singleChoice更改为multipleChoiceModal

我有一个ListView通常是singleChoice choiceMode 。 当用户长按一个项目,我想进入一个动作模式,允许select多个项目,以便他们可以对任何选定的项目执行操作。

我可以configurationListView ,使其处于singleChoice模式,用户可以select列表项来显示其旁边的细节片段,并使列表项本身显示为激活状态。

我也能够configurationListView ,使其处于multipleChoiceModalselect模式,并对项目执行长按启动动作模式并允许多选,但是现在ListView将不允许在正常模式下进行单个select(无动作模式)。

如何获得处于singleChoice模式的ListView,然后在长按项目时将其转换为multipleChoiceModal模式?

这是我能够想出的最接近的:

  1. 将ListView设置为singleChoice模式
  2. 设置ListView的OnItemLongClickListener并在该侦听器中:
    1. 将ListView的OnItemLongClickListener设置为null
    2. 将ListView的choiceMode设置为multipleChoiceModal
    3. 在长按的项目上调用view.performClick()

这种方法有几个问题。

  1. 直到第二次长按一个项目才开始动作模式。
  2. 当我调用getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);onDestroyActionMode我得到一个java.lang.StackOverflowError因为该方法最终试图摧毁行动模式(但我们还没有从摧毁返回)。

Solutions Collecting From Web of "将ListView choiceMode从singleChoice更改为multipleChoiceModal"

我在我的一个程序中使用了这个

我们的ListView.CHOICE_MODE_MULTIPLE_MODAL然后lv.setMultiChoiceModeListener(new ModeCallBack());

  public class ModeCallBack implements ListView.MultiChoiceModeListener{ View mSelectView; TextView mSelectedCount; ArrayList<Long> mCheckedItems; @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(getActivity()); SharedPreferences.Editor edit = pref.edit(); if(item.getItemId() == R.id.bowler_delete){ for(int i=0; i<mCheckedItems.size(); i++){ long id = mCheckedItems.get(i); getActivity().getContentResolver().delete(BowlersDB.CONTENT_URI,BowlersDB.ID+"="+id,null); } }else if(item.getItemId() == R.id.bowler_add_ball){ if(mCheckedItems.size() > 1){ Toast.makeText(getActivity(),"Can only add bowling balls to one bowler at a time",Toast.LENGTH_SHORT).show(); }else{ edit.putLong(Preferences.BOWLER_SELECTED_FOR_BALL,mCheckedItems.get(0)).commit(); ListFragment lf = new ManufacturersList(); FragmentTransaction ft; ft = getFragmentManager().beginTransaction(); ft.replace(R.id.frameOne, lf).addToBackStack(null).commit(); //mRemover.rFragment(); } }else if(item.getItemId() == R.id.add_bowler_to_team){ for(int i=0; i<mCheckedItems.size(); i++){ long id = mCheckedItems.get(i); ContentValues values = new ContentValues(); values.put(TeamBowlers.BOWLER_ID,id); values.put(TeamBowlers.TEAM_ID,pref.getLong(Preferences.TEAM_SELECTED,1)); getActivity().getContentResolver().insert(TeamBowlers.CONTENT_URI, values); } FragmentManager fm = getFragmentManager(); fm.popBackStack(); } mode.finish(); return true; } @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { MenuInflater inflate = getActivity().getMenuInflater(); if(fromTeam){ inflate.inflate(R.menu.bowlers_team_action_menu, menu); }else{ inflate.inflate(R.menu.bowler_action_menu, menu); } if(mSelectView == null){ mSelectView = (ViewGroup)LayoutInflater.from(getActivity()).inflate(R.layout.select_count_layout,null); mSelectedCount = (TextView)mSelectView.findViewById(R.id.count_tv); } if(mCheckedItems == null){ mCheckedItems = new ArrayList<Long>(); } mode.setCustomView(mSelectView); return true; } @Override public void onDestroyActionMode(ActionMode mode) { mCheckedItems = null; } @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { if(mSelectView == null){ mSelectView = (ViewGroup)LayoutInflater.from(getActivity()).inflate(R.layout.select_count_layout,null); mSelectedCount = (TextView)mSelectView.findViewById(R.id.count_tv); } if(mCheckedItems == null){ mCheckedItems = new ArrayList<Long>(); } return true; } @Override public void onItemCheckedStateChanged(ActionMode mode, int position,long id, boolean checked) { final int count = lv.getCheckedItemCount(); mSelectedCount.setText(String.valueOf(count)); if(checked){ mCheckedItems.add(id); }else{ mCheckedItems.remove(id); } } } 

这允许单选listview单击和长按多选。 这一切都从ICS的消息应用程序,所以你也可以浏览

这个select模式开关看起来真的很难,因为我没有干净简单的解决scheme,我可以谷歌。 HFM(有信仰的人)和KISS(保持简单愚蠢)帮助;)

1.以单一模式select启动并设置所有监听器(这是在你设置列表适配器的地方完成的)

 listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE); listView.setOnItemLongClickListener(liListener); listView.setMultiChoiceModeListener(mcListener); 

2.实现界面在select模式之间切换。 使其工作的TRICK是在执行之外切换回单一select模式,意思是在你破坏动作模式后! 所以只需使用一个简单的标志来标记CAB销毁。 另一个TRICK是在ItemLongClick上返回false,以便select模式有时间生效。

 private OnItemLongClickListener liListener = new OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL); isCABDestroyed = false; return false; // so this action does not consume the event!!! } }; private MultiChoiceModeListener mcListener = new MultiChoiceModeListener() { @Override public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) { final int checkedCount = listView.getCheckedItemCount(); switch (checkedCount) { case 0: mode.setSubtitle(null); break; case 1: mode.setSubtitle("One item selected"); break; default: mode.setSubtitle("" + checkedCount + " items selected"); break; } } @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { switch (item.getItemId()) { case R.id.delete: //do your action command here mode.finish(); return true; default: return false; } } @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { MenuInflater inflater = mode.getMenuInflater(); inflater.inflate(R.menu.context_menu, menu); return true; } @Override public void onDestroyActionMode(ActionMode mode) { isCABDestroyed = true; // mark readiness to switch back to SINGLE CHOICE after the CABis destroyed } @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return false; } }; 

这是切换回来的

  @Override public void onListItemClick(ListView l, View v, int position, long id) { super.onListItemClick(l, v, position, id); if(isCABDestroyed) { listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE); //do your action command here } l.setItemChecked(position, true); }