ListView повторно использует представления, когда... я не хочу

У меня есть ListView, каждый из item из которых содержит ToggleButton, После того, как я переключаю его, а затем прокручиваю вверх или вниз, ListView перезапускает Представления, и поэтому некоторые другие отражают проверенное состояние ToggleButton, Я не хочу этого Как я могу предотвратить это?

5 ответов

Решение

Android перерабатывает элементы списка для повышения производительности. Настоятельно рекомендуется использовать их повторно, если вы хотите, чтобы ваш ListView плавно прокручивался.

Для каждого элемента списка getView функция вашего адаптера называется. Там вы должны назначить значения для элемента, который запрашивает ListView.

Посмотрите на этот пример:

@Override
public View getView(int position, View convertView, ViewGroup parent)
{
    ViewHolder holder = null;

    if ( convertView == null )
    {
        /* There is no view at this position, we create a new one. 
           In this case by inflating an xml layout */
        convertView = mInflater.inflate(R.layout.listview_item, null);  
        holder = new ViewHolder();
        holder.toggleOk = (ToggleButton) convertView.findViewById( R.id.togOk );
        convertView.setTag (holder);
    }
    else
    {
        /* We recycle a View that already exists */
        holder = (ViewHolder) convertView.getTag ();
    }

    // Once we have a reference to the View we are returning, we set its values.

    // Here is where you should set the ToggleButton value for this item!!!

    holder.toggleOk.setChecked( mToggles.get( position ) );

    return convertView;
}

Заметить, что ViewHolder это статический класс, который мы используем для переработки этого представления. Его свойства - это представления вашего элемента списка. Это заявлено в вашем адаптере.

static class ViewHolder{
    ToggleButton toggleOk;
}

mToggles объявляется как частное свойство в вашем адаптере и устанавливается с помощью открытого метода, например:

public void setToggleList( ArrayList<Boolean> list ){
        this.mToggles = list;
        notifyDataSetChanged();
    }

Посмотрите другие примеры ListView для получения дополнительной информации.

Надеюсь, поможет.

Добавьте эти два метода к вашему адаптеру.

@Override

public int getViewTypeCount() {                 

    return getCount();
}

@Override
public int getItemViewType(int position) {

    return position;
}

Вы могли бы использовать HashMap чтобы сохранить состояние кнопок:

 private Map<Integer,Boolean> listMapBoolean = new HashMap<Integer,Boolean>();


 toggleButton.setOnCheckedChangeListener(new OnCheckedChangeListener() {
                    @Override
                    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                        if (isChecked) {
                            listMapBoolean.put(position, true);
                        } else {
                            listMapBoolean.put(position, false);
                        }
                    }
                });

и после надувания зрения вы читаете HashMap чтобы увидеть, было ли это проверено или нет:

 for (Entry<Integer, Boolean> entry : listMapBoolean.entrySet()) {
                if (entry.getKey().equals(i)) {
                    if(entry.getValue()) {
                        System.out.println("ToggleButton is checked!");
                    } else {
                        System.out.println("ToggleButton is not checked!");
                    }
                }
            }

Не уверен, поможет ли это на вашем пути. У меня были также проблемы с утилизацией моего EditText в моем ListView,

Это сделало бы его очень медленным для больших списков. Но внутри getView(), вы можете использовать:

      if (listItemView == null || ((int)listItemView.getTag()!=position)) {
            listItemView = LayoutInflater.from(context).inflate(R.layout.edit_text_list_item,
                    parent, false);
}

listItemView.setTag(position);
// set inner Views data from ArrayList
...

Тег представляет собой Objectчто связано с View. И вы проверяете всякий раз, когда перерабатываете его, можете ли вы его переработать или нет. Это делает каждый элемент списка раздутым, и ничего не будет переработано.

Это также должно предотвратить удаление текста из EditTextвнутри, а также предотвратить изменение порядка изображений или их перепутывание, если вы ListViewимеет изображения в нем.

Может быть, вам следует попробовать создать свой собственный вид списка с представлением прокрутки и контейнером, в котором содержатся дочерние элементы, которые добавляются в контейнер программно. установите тег для идентификации ребенка, или вы можете использовать порядок ребенка для этого

Другие вопросы по тегам