Intereting Posts
Следующая кнопка сенсорной клавиатуры Sencha в текстовом поле xtype CursorLoader отменяется, когда действие приостановлено Отредактируйте или удалите разрешение со страницы информации о приложении во время установки приложения Анализ вложенного объекта JSON в Android Поддерживает ли Android поддержку нескольких языков? Выберите текст в edittext при перетаскивании Как мы показываем кнопку «Назад» вместо кнопки «Готово» («галочка») в контекстной панели действий на Android Intel TBB для Android и iOS Сортировка списка с адаптером массива Разница между API Google (системный образ x86) и API Google (изображение системы ARM) в Android 4.4.2 Динамически задавать диалог диалога поиска Android: Могу ли я игнорировать ошибки «Родительское представление – это не TextView» и «sendUserActionEvent () mView == null»? Совместное использование стенового сообщения от facebook android sdk Студия Android не может разрешить com.google.android.gms.location.places.AutocompleteFilter Внешний путь к файлу SDCard для Android

Android listview отображает ложные данные после прокрутки (пользовательский адаптер)

У меня странная проблема, которая сводит меня с ума. В моем приложении Android я настроил свой собственный адаптер, который простирается от ArrayAdapter. Элементы ListView, к которым я добавил свой адаптер, могут быть помечены как текст (не редактируемый), редактируемый текст или прядильщик. Сумасшедшие вещи: когда я просматриваю ListView, есть две проблемы:

(1) значение (выбранное), которое отображается в элементах счетчика, изменяется иногда, хотя я только прокручивал !! Когда я нажимаю на счетчик, старое выбранное значение все еще отображается (тот, который должен отображаться счетчиком) (2) порядок списков ListViewItems изменяется при прокрутке!

=> НО данные в адаптере не изменяются (ни сами данные, ни порядок) – значит, это проблема самого вида? Возможно, андроидные кэши в фоновом режиме и не обновляют ListViewItems достаточно скоро или так?

Может ли кто-нибудь помочь мне, пожалуйста?

Большое спасибо!

Хорошо, я нашел решение, которое не очень приятно, но оно работает. Я просто больше не использовал convertView, хотя это неоптимально относительно памяти и производительности. В моем случае это должно быть нормально, потому что максимальное количество элементов ListView – 15. Вот мой класс адаптера:

public class FinAdapter extends ArrayAdapter<Param>{ public Param[] params; private boolean merkzettel; protected EditText pv; public FinAdapter(Context context, int textViewResourceId, Param[] items, boolean merkzettel) { super(context, textViewResourceId, items); this.params = items; this.merkzettel = merkzettel; } @Override public View getView(int position, View convertView, ViewGroup parent) { final Param p = params[position]; if(p != null){ if(merkzettel){ if (convertView == null) { LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = vi.inflate(R.layout.merk_det_item, null); } TextView tvl = (TextView) convertView.findViewById(R.id.paramM); TextView edl = (TextView) convertView.findViewById(R.id.param_valueM); TextView pal = (TextView) convertView.findViewById(R.id.param_unitM); if (tvl != null) { tvl.setText(p.getName()); } if(pal != null){ pal.setText(p.getUnit()); } if(edl != null){ edl.setText(p.getDefData()); } } else{ if(p.isSelect()){ if (convertView == null) { LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = vi.inflate(R.layout.fin_prod_list_item_select, null); } TextView tvs = (TextView) convertView.findViewById(R.id.paramS); Spinner sp = (Spinner) convertView.findViewById(R.id.spinner_kalk); TextView paU = (TextView) convertView.findViewById(R.id.param_unitS); if (tvs != null) { tvs.setText(p.getName()); } if(paU != null){ paU.setText(p.getUnit()); } if(sp != null){ String[] values = new String[p.getData().size()]; for(int i=0; i<values.length; i++){ values[i] = p.getData().get(i); } ArrayAdapter<String> adapter = new ArrayAdapter<String>(this.getContext(), android.R.layout.simple_spinner_item, values); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); sp.setAdapter(adapter); sp.setSelection(p.getData().indexOf(p.getDefData())); sp.setOnItemSelectedListener(new OnItemSelectedListener(){ public void onItemSelected(AdapterView<?> parent, View convertView, int pos, long id) { p.setDefData(p.getData().get(pos)); p.setChanged(true); } public void onNothingSelected(AdapterView<?> arg0) { // TODO Auto-generated method stub } }); } } else if(p.isEdit()){ if (convertView == null) { LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = vi.inflate(R.layout.fin_prod_list_item_edit, null); } TextView pa = (TextView) convertView.findViewById(R.id.param); pv = (EditText) convertView.findViewById(R.id.param_value); TextView paE = (TextView) convertView.findViewById(R.id.param_unit); if (pa != null) { pa.setText(p.getName()); } if(paE != null){ paE.setText(p.getUnit()); } if(pv != null){ pv.setText(p.getDefData()); pv.setOnEditorActionListener(new OnEditorActionListener(){ public boolean onEditorAction(TextView convertView, int actionId, KeyEvent event) { // TODO Auto-generated method stub p.setDefData(pv.getText().toString()); p.setChanged(true); return false; } }); } } else if(p.isLabel()){ if (convertView == null) { LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = vi.inflate(R.layout.fin_prod_list_item_label, null); } TextView tvl = (TextView) convertView.findViewById(R.id.paramL); TextView edl = (TextView) convertView.findViewById(R.id.param_valueL); TextView pal = (TextView) convertView.findViewById(R.id.param_unitL); if (tvl != null) { tvl.setText(p.getName()); } if(pal != null){ pal.setText(p.getUnit()); } if(edl != null){ edl.setText(p.getDefData()); } }} } return convertView; } } 

У меня была аналогичная проблема с несколькими типами элементов в списке. В моем случае элемент списка был либо элементом раздела (метки), либо общим элементом списка.

Чтобы работать с такими типами списков, вы должны переопределить getViewTypeCount и getItemViewType . Что-то вроде этого:

 private static final int ITEM_VIEW_TYPE_ITEM = 0; private static final int ITEM_VIEW_TYPE_SEPARATOR = 1; @Override public int getViewTypeCount() { return 2; } @Override public int getItemViewType(int position) { return this.getItem(position).isSection() ? ITEM_VIEW_TYPE_SEPARATOR : ITEM_VIEW_TYPE_ITEM; } @Override public View getView(int position, View convertView, ViewGroup parent) { final Item item = this.getItem(position); if (convertView == null) { convertView = mInflater.inflate(item.isSection() ? R.view1 : R.view2, null); } if(item.isSection()){ //... } else{ //... } return convertView; } 

Тогда параметр convertView всегда будет правильным и будет содержать тот тип, который вам нужен.

И еще одно: вы явно добавили public Param[] params поле public Param[] params когда у вас уже есть его в базовом классе ArrayAdapter<Param> .

Я бы рекомендовал наследовать класс BaseAdapter .

Изменить: Вот код, который вы можете попробовать использовать, чтобы заставить Spinner работать:

 sp.setTag(p); sp.setOnItemSelectedListener(new OnItemSelectedListener(){ public void onItemSelected(AdapterView<?> parent, View convertView, int pos, long id) { Param currentItem = (Param)parent.getTag(); currentItem.setDefData(currentItem.getData().get(pos)); currentItem.setChanged(true); } //... 

Попробуйте использовать комбинацию методов getTag и setTag . Я помню, что у меня были подобные проблемы с обработчиками событий и конечными переменными, но я полностью забыл их причину, поэтому я не могу точно объяснить, почему это происходит.

Как упоминалось Сэмом, система Android всегда пытается по возможности утилизировать ресурсы для экономии ресурсов. Это означает, что разработчикам необходимо следить за самим View в ListView . Для объекта или так называемой структуры данных представления вы можете иметь что-то, чтобы отслеживать выбранное / де-выбранное состояние, например:

 class PresentationData { // other stuffs.. boolean isSelected = false; } 

Сопоставление этих структур данных с Adapter , и если какой-либо элемент щелкнул, установите для состояния значение true: listPresentationData.get(selected_position).isSelected = true

Итак, в getView() адаптера, правильно отслеживайте презентацию для своих данных.

 if(listPresentationData.get(position).isSelected) { // set background color of the row layout..or something else } 

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