2011-08-26 11 views
15

Tengo un ListView que muestra 2 tipos de elementos. Uno de estos tipos contiene CheckedTextView. Como adaptador, estoy usando adaptadores personalizados que extienden ArrayAdapter con una estructura de datos que contiene información sobre estados marcados/no comprobados dentro.Configuración del elemento ListView verificado a partir del adaptador

Algunos de los elementos están marcados como seleccionados (en mi estructura de datos) así que por supuesto me gustaría que las casillas de verificación se marquen cuando se crea el ListView. Intenté hacerlo en el método getView() en el adaptador con el método setChecked() de CheckedTextView pero no funciona. Encontré información de que debería hacerse en un nivel de ListView con setItemChecked() y funciona, pero no tiene sentido para mí porque para hacerlo funcionar tendría que hacer un bucle de todos los elementos en la actividad onCreate() llamando a setItemChecked() para aquellos seleccionados La lista de artículos puede ser muy larga, con solo unos pocos seleccionados, por lo que es un desperdicio.

¿Por qué llamar a setChecked() en getView() no está funcionando? ¿Hay una mejor manera de hacerlo (soy un novato de Android).

A continuación, tiene el diseño de mi elemento comprobado y el adaptador.

Diseño:

<?xml version="1.0" encoding="utf-8"?> 
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@android:id/text1" 
    android:layout_width="fill_parent" 
    android:layout_height="?android:attr/listPreferredItemHeight" 
    android:gravity="center_vertical" 
    android:textAppearance="@style/listViewItemText" 
    android:checkMark="?android:attr/listChoiceIndicatorMultiple" 
    android:paddingLeft="6dp" 
    android:paddingRight="6dp" 
/> 

adaptador:

package com.melog.re.droid.search; 

import java.util.ArrayList; 
import java.util.List; 

import android.content.Context; 
import android.os.Parcel; 
import android.os.Parcelable; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.ArrayAdapter; 
import android.widget.CheckedTextView; 
import android.widget.TextView; 

import com.melog.re.droid.core.R; 
import com.melog.re.droid.search.MultiCriterionValue.MultiCriterionSingleValue; 
import com.melog.re.droid.search.MultiListAdapter.MultiChoiceItem; 

public class MultiListAdapter extends ArrayAdapter<MultiChoiceItem> { 
    private static final int VIEW_TYPES_COUNT = 2; 

    public static final int VIEW_TYPE_GROUP = 0; 
    public static final int VIEW_TYPE_ITEM = 1; 

    private LayoutInflater mInflater; 

    public MultiListAdapter(Context context, int textViewResourceId, List<MultiChoiceItem> objects) { 
     super(context, textViewResourceId, objects); 
     mInflater = LayoutInflater.from(context); 
    } 

    @Override 
    public int getItemViewType(int position) { 
     MultiChoiceItem item = getItem(position); 
     return (item.children.size() == 0) ? VIEW_TYPE_ITEM : VIEW_TYPE_GROUP; 
    } 

    @Override 
    public int getViewTypeCount() { 
     return VIEW_TYPES_COUNT; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     // TODO: optymalizacja ViewHolder 
     MultiChoiceItem item = getItem(position); 
     int viewType = getItemViewType(position); 
     switch (viewType) { 
     case VIEW_TYPE_GROUP: 
      if (convertView == null) { 
       convertView = mInflater.inflate(R.layout.multi_choice_group_item, parent, false); 
      } 
      TextView groupLabel = (TextView) convertView.findViewById(android.R.id.text1); 
      groupLabel.setText(item.toString()); 
      break; 
     case VIEW_TYPE_ITEM: 
      if (convertView == null) { 
       convertView = mInflater.inflate(R.layout.multi_choice_child_item, parent, false); 
      } 
      CheckedTextView itemLabel = (CheckedTextView) convertView.findViewById(android.R.id.text1); 
      itemLabel.setText(item.toString()); 
      itemLabel.setChecked(item.selected); 
      break; 
     } 

     return convertView; 
    } 

    public static class MultiChoiceItem implements Parcelable { 
     public static final int CONTENTS_DESCR = 1; 

     public String label; 
     public String value; 
     public boolean selected = false; 
     public ArrayList<MultiChoiceItem> children = new ArrayList<MultiChoiceItem>(); 

     public MultiChoiceItem(String l, String v, boolean sel) { 
      label = l; 
      value = v; 
      selected = sel; 
     } 
     public MultiChoiceItem(MultiCriterionSingleValue v) { 
      label = v.toString(); 
      value = v.value; 
     } 
     public MultiChoiceItem(Parcel in) { 
      label = in.readString(); 
      value = in.readString(); 
      selected = (in.readInt() == 1); 
     } 
     @Override 
     public String toString() { 
      return label; 
     } 
     @Override 
     public int describeContents() { 
      return CONTENTS_DESCR; 
     } 
     @Override 
     public void writeToParcel(Parcel dest, int flags) { 
      dest.writeString(label); 
      dest.writeString(value); 
      dest.writeInt(selected ? 1 : 0); 
     } 

     public static final Parcelable.Creator<MultiChoiceItem> CREATOR = new Parcelable.Creator<MultiChoiceItem>() { 
      public MultiChoiceItem createFromParcel(Parcel in) { 
       return new MultiChoiceItem(in); 
      } 

      public MultiChoiceItem[] newArray(int size) { 
       return new MultiChoiceItem[size]; 
      } 
     }; 
} 
} 

y un trozo de onCreate de la actividad()

...  
mAdapter = new MultiListAdapter(this, R.id.head, mItems); 
setListAdapter(mAdapter); 

final ListView listView = getListView(); 
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); 
listView.setItemsCanFocus(false); 
... 

Editar:

hasta encontrar una mejor solución que he implementado el cheque ing en la Actividad:

... 
int len = mListView.getCount(); 
for (int i = 0; i < len; i++) { 
    if (((MultiChoiceItem) mListView.getItemAtPosition(i)).selected) { 
     mListView.setItemChecked(i, true); 
    } 
} 
... 

pensé que el rendimiento será el único problema potencial, pero me encontré con otra - mucho más grave. La lista tiene filtro de texto habilitado (mListView.setTextFilterEnabled (true)). Aquí está el escenario de error:

  1. estoy abriendo nueva lista
  2. Im comprobar digamos artículo 2-nd
  3. empiezo a escribir para filtrar algunos artículos
  4. cuando el filtrado se realiza, el 2- nd artículo todavía está marcada a pesar de que no es el que he comprobado

asumo que setItemChecked() marca una posición fija en la lista comprobado mientras que necesito algo que marcará el artículo celebrada en la posición THS - manteniendo el estado incluso cuando la posición en la lista cambia.

Si bien el problema de rendimiento podría (en cierto sentido) ignorarse, este nuevo problema realmente me está bloqueando, por lo que agradecería cualquier ayuda con él.

Respuesta

28

Si usa ListView.CHOICE_MODE_MULTIPLE o CHOICE_MODE_SINGLE los estados de verificación de los elementos serán anulados por ListView después de llamar al getView. Usted tiene que utilizar la construcción siguiente:

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    ((ListView)parent).setItemChecked(position, true); 
} 

Otra posibilidad es utilizar ListView.CHOICE_MODE_NONE y gestionar los estados de verificación por sí mismo.

+0

Me enfrento con el mismo problema. Mis elementos marcados desaparecen al desplazar la vista de lista. He intentado con el bloque de código dentro de mi adaptador, pero aún así mis elementos marcados desaparecen al desplazarme por la vista de lista. – salih

+0

Gracias, tuve que buscar bastante tiempo para encontrar una solución. –

-1

Echa un vistazo a los pasos por primera vez en XML tema de hacer los cambios añadir sola línea en casilla de verificación

`android:onClick="chatWithFriend"` 

por lo que cuando el clic en cheackbox a continuación, crear un método en el nombre de la actividad

public void chatWithFriend(View view){} 
here you will get the view of check box, 

Ahora agregue la línea en getView antes de la vista de conversión de retorno

holder.checkbox .setTag (posición);

Ahora u conseguirá la posición de la casilla de verificación

espero que esto le ayudará.

+0

Tal vez no me haya aclarado. No tengo ningún problema para obtener la posición del artículo. Todas las acciones de "hacer clic" funcionan bien. Lo que no funciona es hacer que los elementos seleccionados (esta información esté en los datos pasados ​​al adaptador) se comprueben en la vista de lista recién creada. – Izydorr

+0

esto puede ayudar http://about-android.blogspot.com/2010/04/steps-to-implement-expandablelistview.html –

+0

Lo siento pero no veo cómo esto podría ser útil para mí :( – Izydorr

Cuestiones relacionadas