2011-08-16 7 views
7

Tengo un menú de opciones con una opción "Agregar/Eliminar" que, cuando hace clic, muestra una lista verificable. El problema con el código que tengo actualmente es que solo puede seleccionar un elemento a la vez, y el menú desaparece. Quiero poder verificar múltiples elementos en la lista a la vez, y para que no desaparezca hasta que el usuario toque un lugar en otra parte de la pantalla. ¿Cómo puedo hacer esto? Aquí está la idea general de lo que tengo:¿Cómo seleccionar múltiples casillas de verificación en el submenú en Android?

<?xml version="1.0" encoding="UTF-8"?> 
<menu xmlns:android="http://schemas.android.com/apk/res/android"> 
    <item android:id="@+id/select_options" 
      android:title="Add/Remove"> 
     <menu> 
      <group android:checkableBehavior="all"> 
       <item android:id="@+id/A" 
         android:checked="true" 
         android:title="Option One" /> 
       <item android:id="@+id/B" 
         android:checked="true" 
         android:title="Option Two" /> 
      </group> 
     </menu> 
    </item> 
</menu> 

y

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    MenuInflater inflater = getMenuInflater(); 
    inflater.inflate(R.menu.selection_menu, menu); 
    return true; 
} 

@Override 
public boolean onOptionsItemSelected(MenuItem item){ 
    switch (item.getItemId()){ 
    case R.id.A: 
     item.setChecked(!item.isChecked()); 
     return true; 
    case R.id.B: 
     item.setChecked(!item.isChecked()); 
     return true; 
    default: 
     return super.onOptionsItemSelected(item); 
    } 
} 
+0

¿por casualidad lo averiguaste? Estoy buscando el mismo – Waqas

Respuesta

6

Hola TheBeatlemaniac!

Sinceramente, no sé si lo que usted está buscando es factible o no (EDIT: en la forma en que se lleve a la práctica, como un submenú), pero me hubiera hecho de esta manera:

Crea una actividad que se parece al submenú que deseas mostrar.

Puede parecer un poco más complicado, pero es sencillo y de esta manera, no desaparecerá si selecciona/deselecciona un elemento, y puede implementar mucha más funcionalidad.

Así es como lo habría hecho personalmente:


  • crear una clase para representar un elemento de submenú. Debe contener una cadena (descripción) y un booleano (para almacenar si está marcada o no).
public class SettingCheckBox implements Serializable { 

    private static final long serialVersionUID = 1L; 

    private static final String DEFAULT_DESCRIPTION = "N/A"; 

    private final String description; 

    private boolean checked; 

    public String getDescription() { 
     return description == null ? DEFAULT_DESCRIPTION : description; 
    } 

    public void setChecked (final boolean checked) { 
     this.checked = checked; 
    } 

    public boolean getChecked() { 
     return checked; 
    } 

    public SettingCheckBox (final String description) { 
     this.description = description; 
    } 

} 

Como se puede ver, la clase implementa Serializable para que los objetos de esa clase pueden pasar de una actividad a otra utilizando Propósitos/Lotes.

  • Añadir lo siguiente a su actividad actual (supuse que se llama MainActivity, así que mientras lo intentas, reemplace MainActivity por su nombre de la actividad).
public static final String SETTING_CHECK_BOX = "SETTING_CHECK_BOX"; 

private ArrayList <SettingCheckBox> settingList; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    // ... 
    settingList = new ArrayList <SettingCheckBox>(); 
    settingList.add (new SettingCheckBox ("Option A")); 
    settingList.add (new SettingCheckBox ("Option B")); 
    // ... add more items 
    // restore any previously saved list 
    if (savedInstanceState != null) { 
     settingList = (ArrayList <SettingCheckBox>) savedInstanceState.getSerializable (SETTING_CHECK_BOX); 
    } 
    // ... 
} 

protected void onSaveInstanceState (Bundle outState) { 
    super.onSaveInstanceState (outState); 
    outState.putSerializable (SETTING_CHECK_BOX , settingList); 
} 

La lista (ArrayList) se utiliza para alojar todos los elementos de menú de ajuste sub con las casillas de verificación. Como puede ver, cada objeto SettingCheckBox tiene una descripción y un estado (marcado o no). De forma predeterminada, una vez que se crea, el estado del objeto es desmarcado. Debe inicializar la lista dentro del método onCreate.

La variable estática y última SETTING_CHECK_BOX se utiliza como clave para salvar/restaurar el contenido de la lista antes/después de las reconstrucciones de actividad (como una rotación de la pantalla), y también para pasar la lista configuración de una actividad a otra.(Explicado más adelante)

  • Retirar el submenú, por lo que el archivo XML Menu se ve así:
<?xml version="1.0" encoding="UTF-8"?> 
<menu xmlns:android="http://schemas.android.com/apk/res/android"> 
    <item android:id="@+id/select_options" 
     android:title="Add/Remove"> 
    </item> 
</menu> 

Sin necesidad de que el submenú más ya que se pondrá en práctica una actividad que actúa como uno. Ahora, para unir el elemento de menú para la actividad que va a mostrar la configuración, debe utilizar el método de onOptionsItemSelected dentro de su actividad actual como esto:

@Override 
public boolean onOptionsItemSelected (MenuItem menuItem) { 
    if (menuItem.getItemId() == R.id.select_options) { 
     Intent intent = new Intent (this , MyActivity_Settings.class); 
     intent.putExtra (SETTING_CHECK_BOX , settingList); 
     startActivityForResult (intent , 0); 
    } 
} 

Se inicia la actividad de configuración para obtener un resultado. Significa que se comporta como una actividad secundaria y puede devolver un resultado a su actividad principal.

La lista de configuraciones se transfiere a la actividad de configuración a través del intento.

Si la actividad del niño termina y devuelve los datos a la actividad de los padres, el siguiente método se llama:

protected void onActivityResult (int requestCode , int resultCode , Intent data) { 
    if (resultCode != RESULT_OK || data == null) 
     return; 
    settingList = (ArrayList <SettingCheckBox>) data.getSerializableExtra (SETTING_CHECK_BOX); 
} 

usted debe hacer la actividad del niño/ajustes devuelve la lista (nuevo/modificado) de los ajustes, y como se demostró anteriormente, la nueva lista está configurada.

  • Cree el siguiente archivo XML llamado diseño sub_menu:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="vertical" > 

    <ListView 
     android:id="@android:id/list" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" > 
    </ListView> 

</LinearLayout> 

Ésta es la disposición de la actividad que va a actuar como su submenú. En realidad, es una actividad de lista, y puede contener tantas opciones como desee (simplemente agréguelas a la lista de arreglos declarada en su actividad anterior).

  • Cree el siguiente archivo XML de diseño llamada sub_menu_item:
<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:orientation="horizontal" 
    android:gravity="center_vertical" > 

    <TextView 
     android:id="@+id/option_title" 
     android:layout_width="0dip" 
     android:layout_height="wrap_content" 
     android:layout_weight="1" 
     android:textAppearance="@android:style/TextAppearance.Medium" /> 

    <CheckBox 
     android:id="@+id/option_checkbox" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" /> 

</LinearLayout> 

Ésta es la disposición de cada fila de la lista, hay una vista de texto y la casilla de verificación (al igual que el sub menú que ya estabas usando).

  • crear una nueva clase MyActivity_Settings derecho que debe contener lo siguiente:
public class MyActivity_Settings extends ListActivity { 

    private ArrayList <SettingCheckBox> settingList; 

    @Override 
    public void onCreate (Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView (R.layout.sub_menu); 
     setTitle ("Add/Remove"); 
     settingList = getIntent().getSerializableExtra (MainActivity.SETTING_CHECK_BOX); 
     if (savedInstanceState != null) { 
      settingList = (ArrayList <SettingCheckBox>) savedInstanceState.getSerializable (MainActivity.SETTING_CHECK_BOX); 
     } 
     setListAdapter (new MyActivity_Settings_Adapter (this , R.layout.item_layout , settingList)); 
    } 

    protected void onSaveInstanceState (Bundle outState) { 
     super.onSaveInstanceState (outState); 
     outState.putSerializable (MainActivity.SETTING_CHECK_BOX , settingList); 
    } 

    @Override 
    public void finish() { 
     setResult (RESULT_OK , new Intent().putExtra (MainActivity.SETTING_CHECK_BOX , settingList)); 
     super.finish(); 
    } 

} 

class MyActivity_Settings_Adapter extends ArrayAdapter <SettingCheckBox> { 

    private final LayoutInflater layoutInflater; 
    private final int itemResourceId; 

    // Holder pattern (used instead of findViewById for better performance) 
    static class ViewHolder { 
     public TextView title; 
     public CheckBox checkBox; 
    } 

    // Constructor 
    public MyActivity_Settings_Adapter (ListActivity context, int itemResourceId , List <SettingCheckBox> options) { 
     super (context , itemResourceId , options); 
     layoutInflater = context.getLayoutInflater(); 
     this.itemResourceId = itemResourceId; 
    } 

    // Method called by the list view every time to display a row 
    @Override 
    public View getView (int position , View convertView , ViewGroup parent) { 
     // Declare and initialize the row view 
     View rowView = convertView; 
     // Declare the row view holder 
     ViewHolder viewHolder; 
     // Check if an inflated view is provided 
     if (rowView == null) { 
      // A new view must be inflated 
      rowView = layoutInflater.inflate (itemResourceId , null); 
      // Declare and initialize a view holder 
      viewHolder = new ViewHolder(); 
      // Retrieve a reference to the row title 
      viewHolder.title = (TextView) rowView.findViewById (R.id.option_title); 
      // Retrieve a reference to the row check box 
      viewHolder.checkBox = (CheckBox) rowView.findViewById (R.id.option_checkbox); 
      // Store the view holder as tag 
      rowView.setTag (viewHolder); 
     } // End if 
     else 
     // An inflated view is already provided, retrieve the stored view holder 
     viewHolder = (ViewHolder) rowView.getTag(); 

     // Set the option title 
     viewHolder.title.setText (getItem (position).getDescription()); 
     // Set the option check box state 
     viewHolder.checkBox.setChecked (getItem (position).getChecked()); 
     // Assign a click listener to the checkbox 
     viewHolder.checkBox.setOnClickListener(new OnClickListener() { 

      public void onClick (View checkBox) { 
       // Retrieve the stored view holder 
       ViewHolder viewHolder = (ViewHolder) ((View) checkBox.getParent()).getTag(); 
       // Update the option state 
       getItem (position).setChecked (! getItem (position).getChecked()); 
       // Display the new option state 
       viewHolder.checkBox.setChecked (getItem (position).getChecked()); 
      } 
     }); 

     // Return the row view for display 
     return rowView; 
    } // End of getView 

} 

Esta clase representa la actividad que va a actuar como su submenú. Como dije anteriormente, es una actividad de lista (y por lo tanto debería extender ListActivity). Para mostrar las diversas opciones dentro de la lista, necesita un adaptador (el adaptador de matriz es suficiente para este caso), esa es la función de la clase MyActivity_Settings_Adapter (que extiende ArrayAdapter).

Si la actividad de la lista finaliza (el usuario hace clic en el botón Atrás o en cualquier lugar fuera de la actividad que se muestra como un diálogo), (la actividad) devuelve a la actividad principal la nueva lista de opciones con el nuevo valores.

El adaptador creará cada fila para que se muestre la lista. Además, el adaptador asignará un detector de clics para cada casilla de verificación, de modo que si está marcada (o no seleccionada) la opción se modificará en consecuencia.

Y si hace clic en cualquier lugar fuera del submenú (o simplemente presiona el botón Atrás), el submenú desaparecerá y las selecciones del usuario se conservarán en la matriz booleana en su actividad principal.

Si no está familiarizado con ListActivity y ArrayAdapter, este tutorial sería de mucha ayuda.

  • No se olvide de añadir esto en su archivo XML de manifiesto de Android (en la etiqueta de solicitud):
<activity android:name=".MyActivity_Settings" 
     android:theme="@android:style/Theme.Dialog" /> 

El tema aplicado (@android: Estilo/Theme.Dialog) hará que el la actividad se parece a un submenú.

Espero que ayude! ¡Lo probé y funciona perfectamente! Pruébalo y cuéntame qué sucede.

+0

Excelente respuesta ... –

+0

Awesome Man !!!! – ngoa

+0

¡Genial! Estoy usando el código anterior, pero ¿cómo puedo obtener la lista de elementos que se han revisado cuando se presiona el botón Atrás o cuando regreso a la actividad principal? – choman

Cuestiones relacionadas