2010-06-26 26 views
7

Tengo un ListView dinámico que usa un ArrayAdapter. Cuando se selecciona un nombre de una rueda giratoria, el nombre junto con un icono que muestra si son masculinos o femeninos se agrega al ListView.ListView con ArrayAdapter y ViewHolder agregando iconos al elemento incorrecto

Casi todo es bueno (el nombre se agrega a la lista correctamente, junto con un icono). Pero el ícono que muestra el sexo se agrega al ítem incorrecto en el ListView. El nombre se agrega al final de la lista, pero el icono se coloca en el nombre en la parte superior de la lista. No sé si es la forma en que estoy usando ViewHolder, pero no hay documentación en el Android website.

// Listview inflater 
inflater = (LayoutInflater) (this).getSystemService(LAYOUT_INFLATER_SERVICE); 

// List Array. 
mAdapter = new ArrayAdapter<String>(this, R.layout.player_simple_list, 
               R.id.label, mStrings) { 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 

     Log.i("ANDY","View getView Called"); 
     // A ViewHolder keeps references to children views to 
     // avoid unneccessary calls to findViewById() on each row. 
     ViewHolder holder; 

     if (null == convertView) { 
      Log.i("ANDY","Position not previously used, so inflating"); 
      convertView = inflater.inflate(R.layout.player_simple_list, null); 
      // Creates a ViewHolder and store references to the 
      // two children views we want to bind data to. 
      holder = new ViewHolder(); 
      holder.text = (TextView) convertView.findViewById(R.id.label); 
      holder.icon = (ImageView) convertView.findViewById(R.id.icon); 
      if (sexmale == true) { 
       holder.icon.setImageBitmap(maleicon); 
      } 
      else { 
       holder.icon.setImageBitmap(femaleicon); 
      } 
      convertView.setTag(holder); 
     } else { 
      // Get the ViewHolder back to get fast access to the TextView 
      // and the ImageView. 
      holder = (ViewHolder) convertView.getTag(); 

     } 
     // Bind the data efficiently with the holder. 
     holder.text.setText(getItem(position)); 
     // Change icon depending is the sexmale variable is true or false. 
     Log.i("ANDY","getCount = "+mAdapter.getCount()); 
     return convertView; 
    } 
}; 
setListAdapter(mAdapter); 
+0

Existe algún tipo de documentación que hay justo: https://developer.android.com/training/improving-layouts/smooth-scrolling.html – Vince

Respuesta

1

Actualización:ViewHolder sólo está pensada para contener referencias a las vistas de componentes dentro del diseño de concepto. Esto ayuda a evitar la sobrecarga de llamar al findViewById para representar cada componente dentro de diseños de elementos complejos con varios componentes (como el TextView y el ImageView en este caso).

Lo arreglé usando una rutina (llamada getSex) para recuperar los datos de sexo y configurar todos los datos de vista, incluidos los íconos fuera de los bloques if-else.

El código de trabajo ahora se ve así:

if (null == convertView) { 
    Log.i("ANDY","Position not previously used, so inflating"); 
    convertView = inflater.inflate(R.layout.player_simple_list, null); 

    // Creates a ViewHolder and store references to the two children views 
    // we want to bind data to. 
    holder = new ViewHolder(); 
    holder.text = (TextView) convertView.findViewById(R.id.label); 
    holder.icon = (ImageView) convertView.findViewById(R.id.icon); 
    convertView.setTag(holder); 
} else { 
    // Get the ViewHolder back to get fast access to the TextView 
    // and the ImageView. 
    holder = (ViewHolder) convertView.getTag(); 
} 

// Bind the data efficiently with the holder. 
holder.text.setText(getItem(position)); 
// Change icon depending is the sexmale variable is true or false. 
if (getSex (getItem(position)) == true) { 
    holder.icon.setImageBitmap(maleicon); 
} 
else { 
    holder.icon.setImageBitmap(femaleicon); 
} 
return convertView; 
1

Hay que pasar de la FI unas pocas líneas de datos después del comentario, como en este question is explained

// Bind the data efficiently with the holder. 

por lo que se verá así

if (null == convertView) { 
    Log.i("ANDY","Position not previously used, so inflating"); 
    convertView = inflater.inflate(R.layout.player_simple_list, null); 
    // Creates a ViewHolder and store references to the two children views 
    // we want to bind data to. 
    holder = new ViewHolder(); 
    convertView.setTag(holder); 
} else { 
    // Get the ViewHolder back to get fast access to the TextView 
    // and the ImageView. 
    holder = (ViewHolder) convertView.getTag(); 
} 

// Bind the data efficiently with the holder. 
holder.text = (TextView) convertView.findViewById(R.id.label); 
holder.icon = (ImageView) convertView.findViewById(R.id.icon); 
if (sexmale == true) { 
    holder.icon.setImageBitmap(maleicon); 
} 
else { 
    holder.icon.setImageBitmap(femaleicon); 
} 
holder.text.setText(getItem(position)); 
+3

no estoy de acuerdo, esto hará que el 'ViewHolder' sea inútil ya que lo sobrescribes todo el tiempo. La solución correcta debería establecer 'holder.text' y' holder.icon' dentro de la rama 'if' y establecer los contenidos (' setText', 'setImageBitmap') fuera del bloque' if'. – cristis

+0

Creo que la sobrescritura debe estar allí porque si no, guardará los datos relacionados con alguna otra posición de registro. Por ejemplo, muestra el registro 10, y si reutiliza la vista de caché desde el registro 3, si no sobrescribe, el conjunto de datos para el registro 3 estará visible para el registro 10. – Pentium10

+1

@ Pentium10: no, cristis está en lo cierto. El 'ViewHolder' está vinculado a la fila, por lo que los widgets que contiene no cambian. Lo que debe cambiar simplemente es el contenido de esos widgets. – CommonsWare

2

Tienes que configure los iconos después de if-else-if para crear o enlazar un holder. De lo contrario, los iconos se mostrarán correctamente solo en los primeros elementos de la lista, es decir, hasta que no se complete el ListView.

public View getView(int position, View convertView, ViewGroup parent) { 

    Log.i("ANDY","View getView Called"); 
    // A ViewHolder keeps references to children views 
    // to avoid unneccessary calls to findViewById() on each row. 
    ViewHolder holder; 

     if (null == convertView) { 
      Log.i("ANDY","Position not previously used, so inflating"); 
      convertView = inflater.inflate(R.layout.player_simple_list, null); 

      // Creates a ViewHolder and store references to 
      // the two children views we want to bind data to. 
      holder = new ViewHolder(); 
      holder.text = (TextView) convertView.findViewById(R.id.label); 
      holder.icon = (ImageView) convertView.findViewById(R.id.icon); 
      convertView.setTag(holder); 
     } else { 
      // Get the ViewHolder back to get fast access to the TextView 
      // and the ImageView. 
      holder = (ViewHolder) convertView.getTag(); 

     } 
     // Bind the data efficiently with the holder. 
     holder.text.setText(getItem(position)); 

     // Change icon depending is the sexmale variable is true or false. 
     if (sexmale == true) { 
      holder.icon.setImageBitmap(maleicon); 
     } 
     else { 
      holder.icon.setImageBitmap(femaleicon); 
     } 
     Log.i("ANDY","getCount = "+mAdapter.getCount()); 
     return convertView; 
} 
+0

Hola. Intenté esto, pero todos los íconos cambian al mismo tipo, todo en la lista. es decir, si se selecciona un nombre masculino, todos los iconos se vuelven masculinos. –

Cuestiones relacionadas