Кнопка в списке с шаблоном держателя

У меня есть список, который содержит кнопку в каждой строке.

Кнопка открывает диалог для выбора одного значения при нажатии.

Дело в том, что когда я перемещаюсь вниз по списку, значения в кнопках перемещаются. Первое значение повторяется каждые 8 ​​строк.

Вот мой код getView():

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;
}

person Juliatzin    schedule 23.07.2014    source источник
comment
Android перезапускает представления при прокрутке для экономии памяти. Вместо того, чтобы использовать convertView, создайте новое представление View v = vi.inflate(...).   -  person RoraΖ    schedule 23.07.2014
comment
Использование convertview для повышения производительности. У него должен быть способ исправить это, не создавая представление в каждой строке. В противном случае мой список не будет текучим.   -  person Juliatzin    schedule 23.07.2014
comment
Вы реализовали getItemType()? Вот ответ с большим количеством полезной информации о правильной реализации пользовательского адаптера ListView. stackoverflow.com/ вопросы/9712494/   -  person RoraΖ    schedule 23.07.2014
comment
Tx для ссылки, это очень полезно, но я понимаю, что getItemType применяется, когда у меня разные макеты для каждой ячейки. Я ошибся?   -  person Juliatzin    schedule 23.07.2014
comment
Я думаю, что вам, по сути, нужно сбросить customView перед его использованием. Таким образом, вы знаете, что ранее хранившиеся данные (если они были) очищены.   -  person RoraΖ    schedule 23.07.2014


Ответы (2)


Поскольку представления перерабатываются, устанавливайте OnClickListener только в том случае, если convertView == null. См. следующий обновленный код:

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;
}
person hfann    schedule 23.07.2014
comment
Переменная position в getView() содержит информацию о позиции, запрошенную элементом управления для отображения материала. Когда пользователь взаимодействует с кнопкой в ​​строке, getView() не вызывается. Поэтому сохраните значение позиции в объекте ViewHolder и установите значение holder.pos = position; вне блока if(convertView == null). Используйте holder.pos в своем OnClickListener вместо position. - person hfann; 23.07.2014

Простое решение, найденное на этой странице: 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);


}
person Juliatzin    schedule 23.07.2014