我有一个ListView,通常是singleChoice
choiceMode
。当用户长按某个项目时,我想进入一个动作模式,允许选择多个项目,以便他们可以对任何选定的项目执行操作。
我可以配置ListView
以使其处于singleChoice
模式,并且用户可以选择列表项以显示其旁边的详细信息片段,并使列表项本身显示在它的激活状态。
我还可以配置ListView
,使其位于multipleChoiceModal
choiceMode
中并对项目执行长按,启动操作模式并允许多项选择,但现在ListView不允许在正常模式下进行单个选择(无动作模式)。
如何在singleChoice
模式下使用ListView,然后在长按项目时将其转换为multipleChoiceModal
模式?
这是我能够提出的最接近的:
singleChoice
模式OnItemLongClickListener
并在该侦听器中:
OnItemLongClickListener
设置为null
choiceMode
设置为multipleChoiceModal
view.performClick()
。这种方法有几个问题。
getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
中呼叫onDestroyActionMode
时,我得到java.lang.StackOverflowError
因为该方法最终也试图销毁动作模式(但我们还没有从破坏中返回)。 答案 0 :(得分:6)
这个选择模式切换真的很糟糕,因为我没有干净简单的解决方案。 HFM(有信仰的人)和KISS(保持简单的愚蠢)帮助;)
1.启动单模式选择并设置所有侦听器(这是在设置列表适配器的地方完成的)
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
listView.setOnItemLongClickListener(liListener);
listView.setMultiChoiceModeListener(mcListener);
2.实现接口以在选择模式之间切换。让它工作的TRICK是在实现之外切换回单选模式,这意味着在你破坏动作模式之后!所以只需使用一个简单的标志来标记CAB破坏。另一个TRICK是返回false onItemLongClick,以便选择模式有时间生效。
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;
}
};
3.这是切换回来
@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);
}
答案 1 :(得分:3)
我在我的一个程序中使用过它
我们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);
}
}
}
这允许单选单列表视图单击并长按多个选择。这些都来自ICS消息传递应用程序,因此您也可以浏览