0

I have a listview that contains a botton in each row.

The button open a dialog for single value choice when clicked.

The thing is when I move down the list, values in the buttons are moving. The first value is repeated each 8 rows.

Here is my getView() Code :

public static class ViewHolder {
    public Button listaCerrada;
}


    public View getView(final int position, View convertView, ViewGroup parent) {
    final ViewHolder holder;
    try {
        if (convertView == null) {
            holder = new ViewHolder();
            LayoutInflater vi = (LayoutInflater) ctx
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = vi.inflate(R.layout.row_lista_form, null);

            holder.listaCerrada = (Button) convertView
                    .findViewById(R.id.listaCerrada);
            }
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        holder.listaCerrada.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // Get list Values
                String datoValido = metrica.getlForms().get(position)
                        .getProducto().getDatoValido();
                AlertDialog.Builder adb = new AlertDialog.Builder(ctx);
                // HAY:HAY;NO HAY:NO HAY
                String[] parts = datoValido.split(";");
                ArrayList<String> values = new ArrayList<String>();
                for (String s : parts) {
                    String[] part2 = s.split(":");
                    values.add(part2[0]);
                }

                final CharSequence[] items = values
                        .toArray(new CharSequence[values.size()]);

                adb.setSingleChoiceItems(items, 0,
                        new DialogInterface.OnClickListener() {

                            @Override
                            public void onClick(DialogInterface dialog,
                                    int which) {
                                dialog.dismiss();

                                holder.listaCerrada.setText(items[which]);
                            }

                        });
                adb.setNegativeButton("Cancelar", null);


                adb.show();

            }
        });


    } catch (Exception e) {
        e.printStackTrace();
    }
    return convertView;
}
Juliatzin
  • 18,455
  • 40
  • 166
  • 325
  • Android recycles views as you scroll to save memory. Rather than using convertView, create a new view View v = vi.inflate(...). – RoraΖ Jul 23 '14 at 15:36
  • Using convertview is to get better performance. It should have a way to fix it without creating a view in each row. Otherwise, my list will not be fluid. – Juliatzin Jul 23 '14 at 15:38
  • Have you implemented getItemType()? Here's an answer with a lot of good information about correctly implementing a custom ListView adapter. http://stackoverflow.com/questions/9712494/getview-called-with-wrong-position-when-scrolling-fast – RoraΖ Jul 23 '14 at 15:51
  • Tx for the link, it is very useful, but I understand getItemType applies when I have different layouts for each cell. Am I wrong? – Juliatzin Jul 23 '14 at 16:50
  • I think what you essentially have to do is reset customView before you use it. That way you know that the data previously held (if any) is cleared. – RoraΖ Jul 23 '14 at 17:15

2 Answers2

1

Since views are recycled, only set the OnClickListener when convertView == null. See the following updated code:

public View getView(final int position, View convertView, ViewGroup parent) {
    final ViewHolder holder;
    try {
        if (convertView == null) {
            holder = new ViewHolder();
            LayoutInflater vi = (LayoutInflater) ctx
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = vi.inflate(R.layout.row_lista_form, null);

            holder.listaCerrada = (Button) convertView
                    .findViewById(R.id.listaCerrada);
            }

            holder.listaCerrada.setOnClickListener(new OnClickListener() {

               @Override
               public void onClick(View v) {
                  // Get list Values
                  String datoValido = metrica.getlForms().get(position)
                        .getProducto().getDatoValido();
                  AlertDialog.Builder adb = new AlertDialog.Builder(ctx);
                  // HAY:HAY;NO HAY:NO HAY
                  String[] parts = datoValido.split(";");
                  ArrayList<String> values = new ArrayList<String>();
                  for (String s : parts) {
                     String[] part2 = s.split(":");
                     values.add(part2[0]);
                  }

                  final CharSequence[] items = values
                        .toArray(new CharSequence[values.size()]);

                  adb.setSingleChoiceItems(items, 0,
                        new DialogInterface.OnClickListener() {

                            @Override
                            public void onClick(DialogInterface dialog,
                                  int which) {
                               dialog.dismiss();

                               holder.listaCerrada.setText(items[which]);
                            }

                        });
                  adb.setNegativeButton("Cancelar", null);


                  adb.show();

               }
            });

            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

    } catch (Exception e) {
        e.printStackTrace();
    }
    return convertView;
}
hfann
  • 599
  • 3
  • 13
  • 1
    The position variable in getView() contains the position information requested by the control to display stuff. When the user interact with the button on a row, the getView() doesn't get called. Therefore, save the position value in your ViewHolder object and set the value `holder.pos = position;` outside the if(convertView == null) block. Use `holder.pos` in your OnClickListener instead of `position`. – hfann Jul 23 '14 at 17:11
0

Easy solution found with this page : http://blog.mettletech.co/wp/blog/settag-and-gettag-on-listview/

if (convertView == null) {
...
}else{
       holder = (ViewHolder) convertView.getTag();
 // ADD THIS
        Formulario f = lForm.get(position);
        String cantidad = f.getCantidad();
        holder.listaCerrada.setText(cantidad);


}
Juliatzin
  • 18,455
  • 40
  • 166
  • 325