2012-04-20 6 views
8

Ich habe eine ListView, die normalerweise die singleChoice ist. Wenn der Benutzer lange auf ein Element drückt, möchte ich in einen Aktionsmodus wechseln, in dem mehrere Elemente ausgewählt werden können, um eine Aktion für ausgewählte Objekte auszuführen.ListView ändern choiceMode von singleChoice zu multipleChoiceModal

Ich kann die ListView so konfigurieren, dass es in singleChoice Modus ist und der Benutzer in der Lage ist, Listenelemente auszuwählen, um ein Detailfragment daneben anzuzeigen und das Listenelement selbst in seinem aktivierten Zustand angezeigt zu haben.

Ich bin auch in der Lage, die ListView so zu konfigurieren, dass es in der multipleChoiceModalchoiceMode ist und auf ein Element langes Drücken der Durchführung startet die Action-Modus und Mehrfachauswahl erlaubt, aber jetzt ist die Listview wird eine einzige Auswahl in der normalen nicht zulassen, Modus (kein Aktionsmodus).

Wie kann ich einen ListView im singleChoice Modus haben und ihn dann in den multipleChoiceModal Modus umschalten, wenn ein Objekt lange gedrückt wird?

Dies ist die nächste, die ich habe in der Lage zu kommen mit:

  1. stellen Sie die Listview singleChoice Modus
  2. das Listview Besteck OnItemLongClickListener und in diesem Hörer:
    1. das Listview Besteck OnItemLongClickListener zu null
    2. setzen Sie die ListView zu multipleChoiceModal
    3. rufen Sie view.performClick() auf dem Objekt auf, das lange gedrückt wurde.

Dieser Ansatz hat ein paar Probleme.

  1. Der Aktionsmodus wird erst beim zweiten Drücken auf ein Element gestartet.
  2. Wenn ich getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE); in onDestroyActionMode rufe, bekomme ich eine java.lang.StackOverflowError, weil diese Methode versucht, auch den Aktionsmodus zu zerstören (aber wir sind noch nicht von der Zerstörung zurückgekehrt).
+0

, was passieren soll, nachdem Sie multipleChoiceMode eingeben, ausgewählt 2 und die zurück zu singleCheckMode? – user387184

Antwort

3

Ich habe dies in einem meiner Programme

uns die ListView.CHOICE_MODE_MULTIPLE_MODAL dann 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); 
     } 
    } 

} 

dies für einzelne Wahl einzelne Listenansicht klicken und langer Klick Mehrfachauswahl ermöglicht. Dies wurde alles aus der ICS-Messaging-App gezogen, so dass Sie das auch durchsuchen können

+0

Vielleicht fehlt mir etwas, aber wie geht die Liste in den singleChoiceMode, nachdem der Aktionsmodus zerstört wurde? –

+0

überschreiben Sie einfach das 'onListItemClick' in der Listenansicht. Wenn der Benutzer auf das Element in der Listenansicht klickt, wird das Fragment angezeigt, das zu dem Klick gehört. Es sei denn, ich verpasse hier etwas? – tyczj

+0

Ich denke, der Teil, den ich nicht erwähnt habe, ist, dass meine Listenelemente die Vorteile von state_activated nutzen. state_activated only wird auf true gesetzt, wenn das Element tatsächlich als Auswahl im singleChoice-Modus ausgewählt ist. Daher möchte ich wirklich, dass mein ListView wieder in den singleChoice-Modus wechselt. –

5

Es schien wirklich awkard diese Wahl Modus wechseln, da es keine saubere und einfache Lösung, die ich googlen könnte. HFM (glaube Mann) und KISS (Keep it simple stupid) geholfen;)

1.Start im Single-Modus Wahl und stellen Sie alle Hörer (dies geschehen ist, wo Sie die Liste Adapter-Set)

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

2.Implementieren Sie die Schnittstellen, um zwischen den Auswahlmodi zu wechseln. Der TRICK, um es zum Laufen zu bringen, ist, außerhalb der Implementierung zurück in den Single-Choice-Modus zu wechseln, das heißt, NACHDEM du den Aktionsmodus zerstörst !! Verwenden Sie einfach ein einfaches Flag, um die CAB-Zerstörung zu markieren. Ein weiterer Trick besteht darin, false onItemLongClick zurückzugeben, damit der Auswahlmodus Zeit hat, um in Kraft zu treten.

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.Here ist der Schalter zurück

@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); 

    } 
+0

Es tut mir leid, einen alten Post zurück zu bringen, aber ich habe den oben beschriebenen Weg versucht, aber meine ListView-Elemente sind nicht blau markiert (wie auf WhatsApp). Wie kann ich das erreichen? Vielen Dank ! – Leonardo

+0

Wenn die UI Navigation benötigt und zurückkehrt (z. B. wenn die Benutzeroberfläche auf dem Fragment basiert), vergessen Sie nicht, den Status "ListView" in "ListVIEW.CHOICE_MODE_SINGLE" zu ändern, wenn er sich in "ListVIEW.CHOICE_MODE_MULTIPLE_MODAL" befand. Halten Sie außerdem die Wahlmöglichkeit zwischen MULTI und SINGLE. Ich mache es so: if (! IsCABDestroyed) { \t int Auswahl = contentList.getCheckedItemPositions(). KeyAt (0); \t contentList.setChoiceMode (ListView.CHOICE_MODE_SINGLE); \t contentList.setItemChecked (selection, true); } // machen Sie die Navigation weg – StAlex