2012-04-20 11 views
8

Tengo un ListView que normalmente es singleChoicechoiceMode. Cuando el usuario presiona un elemento por mucho tiempo, quiero ingresar a un modo de acción que permite seleccionar varios elementos para que puedan realizar una acción en los elementos seleccionados.Cambiar ListaVer elecciónMode de single Escoger a múltiple EscogerModal

Puedo configurar el ListView de modo que esté en el modo singleChoice y el usuario puede seleccionar elementos de la lista para mostrar un fragmento de detalles al lado y mostrar el elemento de la lista en su estado activado.

También soy capaz de configurar el ListView por lo que es en el multipleChoiceModalchoiceMode y realizar una pulsación larga en un artículo inicia el modo de acción y permite múltiples selecciones, pero ahora el ListView no permitirá que una única selección en la normalidad modo (sin modo de acción).

¿Cómo puedo tener un ListView que está en el modo singleChoice y luego pasarlo al modo multipleChoiceModal cuando se presiona un elemento por un tiempo?

Esto es lo más cerca que he sido capaz de llegar a:

  1. establecer el ListView a singleChoice modo
  2. establecer el ListView de OnItemLongClickListener y en ese oyente:
    1. establecer el ListView de OnItemLongClickListener a null
    2. establece el ListView choiceMode a multipleChoiceModal
    3. llame al view.performClick() en el elemento que se presionó durante mucho tiempo.

Este enfoque tiene un par de problemas.

  1. El modo de acción no se inicia hasta la segunda vez que presiono prolongadamente un elemento.
  2. Cuando llamo al getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE); en onDestroyActionMode obtengo un java.lang.StackOverflowError porque ese método también termina destruyendo el modo de acción (pero aún no hemos regresado del destructor).
+0

lo que debería ocurrir después de introducir multipleChoiceMode, selecciona 2 y el volver a singleCheckMode? – user387184

Respuesta

3

He utilizado este en uno de mis programas

nosotros el ListView.CHOICE_MODE_MULTIPLE_MODAL continuación 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); 
     } 
    } 

} 

esto permite una sola opción única listview clic y clic largo selección múltiple. Todo esto fue extraído de la aplicación de mensajería de ICS para que usted también pueda examinarlo

+0

Quizás me falta algo, pero ¿cómo va la lista a singleChoiceMode después de que se destruye el modo de acción? –

+0

simplemente anule el 'onListItemClick' en la vista de lista y luego, cuando el usuario haga clic en el elemento en la vista de lista, muestre el fragmento que pertenece al clic. a menos que me falta algo aquí? – tyczj

+0

Supongo que la parte que no mencioné es que mis elementos de lista aprovechan state_activated. state_activated only se establece en true cuando el elemento se selecciona realmente como una opción en el modo singleChoice, por lo que realmente quiero que mi ListView cambie de nuevo al modo singleChoice. –

5

Pareció realmente incómodo este cambio de modo de elección ya que no hay una solución limpia y simple que pueda googlear. HFM (tener fe el hombre) y un beso (mantenerlo simple estúpido) ayudó;)

1.Start en la elección de modo único y establecer todos los oyentes (esto se hace donde se configura el adaptador de la lista)

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

2.implementar las interfaces para cambiar entre los modos de elección. El truco para hacerlo funcionar es volver al modo de opción única fuera de la implementación, lo que significa DESPUÉS de que destruyas el modo de acción. Entonces use una bandera simple para marcar la destrucción del CAB. Otro truco es devolver falso onItemLongClick para que el modo de elección tenga tiempo para entrar en vigor.

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 es el interruptor de nuevo

@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

Perdón por traer de vuelta una publicación anterior pero he intentado de la manera descrita anteriormente, pero mis artículos listView no están resaltados en azul (como en whatsapp). ¿Cómo puedo hacer que eso suceda? Gracias ! – Leonardo

+0

Si la IU requiere navegar y regresar a través de la recreación (por ejemplo, cuando la IU se basa en el Fragmento), no olvide cambiar el estado de ListView a 'ListView.CHOICE_MODE_SINGLE' si estaba en' ListView.CHOICE_MODE_MULTIPLE_MODAL' en el momento de desaparecer. Además, mantenga la selección diring cambiando de MULTI a SINGLE. Lo hago así: if (! IsCABDestroyed) { \t int selection = contentList.getCheckedItemPositions(). KeyAt (0); \t contentList.setChoiceMode (ListView.CHOICE_MODE_SINGLE); \t contentList.setItemChecked (selección, verdadero); } // hacer la navegación de distancia – StAlex