Форум программистов, компьютерный форум CyberForum.ru

Программирование Android

Войти
Регистрация
Восстановить пароль
 
Sleep37
4 / 4 / 1
Регистрация: 06.01.2013
Сообщений: 16
#1

Не понятное поведение BaseAdapter - Программирование Android

12.08.2014, 11:51. Просмотров 702. Ответов 7
Метки нет (Все метки)

Добрый день!
Проблема в следующем: есть ListView, есть адаптер унаследованный от BaseAdapter.
В адаптере в методе getView загружаю лайоут, на лайоуте два элемента TextView и Button.
На кнопку вешаю обработчик onClick, при вызове которого в TextView, (который рядом с кнопкой) пишу текст, например: - ok. Проблема в том, что это срабатывает не только для одного TextView во всем ListView, а для каждого TextView который находится на новом экране.
Т.е например во всем ListView 10, на экране отображается по 5 элементов, получается 2 экрана, при клике на самую первую кнопку, TextView изменится в 0 позиции ( т.е самый первый ) и в 6 ( т.к 6 позиция расположена на другом экране)

код адаптера:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public class MYAdapter extends BaseAdapter{
 
    private List<String> items;
    private LayoutInflater layoutInflater;
    public MYAdapter(Context context, List<String> items) {
        this.items = items;
        this.layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }
 
    @Override
    public int getCount() {
        return items.size();
    }
 
    @Override
    public String getItem(int position) {
        return items.get(position);
    }
 
    @Override
    public long getItemId(int position) {
        return position;
    }
 
    @Override
    public View getView(final int position, View convertView, final ViewGroup parent) {
        ViewHolder viewHolder;
        if(convertView == null){
            convertView = layoutInflater.inflate(R.layout.item, null);
            viewHolder = new ViewHolder();
            viewHolder.button = (Button) convertView.findViewById(R.id.button);
            convertView.setTag(viewHolder);
        }else{
            viewHolder = (ViewHolder) convertView.getTag();
        }
        viewHolder.button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                View rootView = (View) v.getParent();
                TextView txt = (TextView) rootView.findViewById(R.id.text);
                txt.setText("OK");
            }
        });
        return convertView;
    }
    static class ViewHolder{
        Button button;
    }
}
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
12.08.2014, 11:51     Не понятное поведение BaseAdapter
Посмотрите здесь:

BaseAdapter - Программирование Android
Есть контейнер для фрагментов (container), есть фрагмент (fragment), есть BaseAdapter и Product Я хочу сделать адаптер из списка в...

BaseAdapter - Программирование Android
Доброго времени суток Есть класс адаптера скопированный с http://idev.by/android/311/ Код: package ru.myscanner.scannerth; ...

Не вижу абстрактных методов в классе BaseAdapter - Программирование Android
Когда создаю свой класс, наследующий BaseAdapter, требуется реализовать 4 абстрактных метода: getCount(), getItem(), getItemId, getView....

Изменение данных через BaseAdapter в Activity - Программирование Android
Добрый день, у меня возникла следующая проблема. У меня имеется стандартное активити с listview и в этом же активити сверху имеется text...

Как вывести в BaseAdapter картинки, занесенные в таблицу? - Программирование Android
Всем привет! Подскажите пожалуйста, как вывести в BaseAdapter картинки которые я занес в таблицу @Override public View...

При клики в BaseAdapter меняется массив строк, как пересоздать ListView с новым массивом? - Программирование Android
Здравствуйте! Имеется класс: package ru.contedevel.mathworker; import java.util.ArrayList; import...

После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
YuraAAA
1566 / 1308 / 269
Регистрация: 25.10.2009
Сообщений: 3,424
Записей в блоге: 2
12.08.2014, 15:17     Не понятное поведение BaseAdapter #2
Цитата Сообщение от Sleep37 Посмотреть сообщение
@Override public void onClick(View v) { View rootView = (View) v.getParent(); TextView txt = (TextView) rootView.findViewById(R.id.text); txt.setText("OK"); }
на

Java
1
2
3
4
 @Override
            public void onClick(View v) {
TextView.class.cast(v).setText("OK");
}
v это всегда будет нужная TextView
Sleep37
4 / 4 / 1
Регистрация: 06.01.2013
Сообщений: 16
12.08.2014, 15:50  [ТС]     Не понятное поведение BaseAdapter #3
не помогло (
NiRamz
211 / 211 / 16
Регистрация: 26.12.2010
Сообщений: 691
12.08.2014, 18:22     Не понятное поведение BaseAdapter #4
Создаем
Java
1
2
3
4
5
6
7
8
9
10
11
12
   private class MyListener implements View.OnClickListener {
 
        private ViewHolder viewHolder;
        public MyListener(ViewHolder vh) {
            viewHolder = vh;
        }
 
        @Override
        public void onClick(View v) {
            vh.textView.setText("ok");
        }
    }
и вешаем его

Java
1
viewHolder.button.setOnClickListener(new MyListener(viewHolder));
Sleep37
4 / 4 / 1
Регистрация: 06.01.2013
Сообщений: 16
14.08.2014, 00:11  [ТС]     Не понятное поведение BaseAdapter #5
NiRamz, работает, но при скрытии элемента всё сбивается. Т.е я нажал на вторую кнопку, после пролистал вниз. пролистал вверх и всё сбилось.(стал отображаться ни текст который был установлен в onClik'e)
а текст который был задан в android:text="New Text"
646kapeh064
59 / 58 / 15
Регистрация: 09.12.2013
Сообщений: 206
14.08.2014, 00:16     Не понятное поведение BaseAdapter #6
Sleep37, потому-что элементы списка пересоздаются (невидимые элементы удаляются, чтоб не загружать память мусором).
Храни например в своём ViewHolder введенный текст в текстовое поле.
NiRamz
211 / 211 / 16
Регистрация: 26.12.2010
Сообщений: 691
14.08.2014, 11:10     Не понятное поведение BaseAdapter #7
Цитата Сообщение от 646kapeh064 Посмотреть сообщение
Sleep37, потому-что элементы списка пересоздаются (невидимые элементы удаляются, чтоб не загружать память мусором).
Храни например в своём ViewHolder введенный текст в текстовое поле.
Не пересоздаются, если правильно создан адаптер, а подтягиваются из кэша вьюх.
Что бы запомнить, на какой позиции был введен текст, создаем небольшой кэш в адаптере, куда пихаем позиции элементов и в getView проверяем его, если там есть такая позиция, назначаем полю нужный текст
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
03.02.2015, 23:19     Не понятное поведение BaseAdapter
Еще ссылки по теме:

Непонятное поведение ArrayList - Программирование Android
У меня есть код, который циклом достаёт данные из базы данных и помещает их в HashMap, а оттуда уже типа HashMap помещает в ArrayList....

Непонятное поведение программы! - Программирование Android
есть счетчик, который выводит цифры в TextView (подобие секундомера) есть кнопка запуска, она же остановки счетчика. Кнопка...

Неадекватное поведение адаптера ListView - Программирование Android
Собственно есть кастом-адаптер. В него приходят два массива с данными. В dates находится даты в формате &quot;29.05.15&quot;. В photos ссылки на...

Непонятное поведение многопоточного приложения - Программирование Android
Всем добрый день. Ввожу в курс дела: я пишу игру под android и мне потребовалась в игре небольшая система, которая будет рендерить пул...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
kvaka
29 / 29 / 3
Регистрация: 26.06.2012
Сообщений: 163
03.02.2015, 23:19     Не понятное поведение BaseAdapter #8
Там система такая. Вообще для отображения элементов вьюх, являющимися позициями списка используется ограниченное число элементов. Т.е., допустим, одновременно на экране может отображаться не более 3х позиций. Для полного функционирования Андроид создает 4 вьюхи (в общем случае, может и больше) - те, которые сейчас на экране и та, которая будет использована для вьюхи, которая появится на экране при скролле. Вьюха, ушедшая за пределы отображаемой области попадает в специальный объект, называемый Recycler, который и использует его для создания нового элемента списка. Поэтому в getView мы и делаем проверку на cjnvertView == null. Т.е. если он null - то у нас нету объекта в ресайклере, который может быть использован для создания позиции списка, соответственно и наполнение у него будет такое, какое при создании инфлейтером из лейаута. В твоем же случае - ты внес в элемен изменение - изменил текст, в этом виде вьюха уехала за экран, далее при создании новой позиции используется та же вьюха. Наполнение текста в getView ты здесь не контролируешь, поэтому он остается таким, каким он уезжал за экран. Таким образом - выводимый на текстВью позиции списка у тебя должен каждый раз доставаться в getView независимо от того создаешь ты вьюху заново или переиспользуешь. Соответственно информацию о нажатых вьюхах ты должен где-то сохранять

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
public class MYAdapter extends BaseAdapter{
 
    private HashSet<Integer> pressedPositions; // здесь будешь хранить номера нажатых позиций
 
    private List<String> items;
    private LayoutInflater layoutInflater;
    public MYAdapter(Context context, List<String> items) {
        this.items = items;
        this.layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
 
        pressedPositions = new HashSet();
    }
 
    @Override
    public int getCount() {
        return items.size();
    }
 
    @Override
    public String getItem(int position) {
        return items.get(position);
    }
 
    @Override
    public long getItemId(int position) {
        return position;
    }
 
    @Override
    public View getView(final int position, View convertView, final ViewGroup parent) {
        ViewHolder viewHolder;
        if(convertView == null){
            convertView = layoutInflater.inflate(R.layout.item, null);
            viewHolder = new ViewHolder();
            viewHolder.button = (Button) convertView.findViewById(R.id.button);
            viewHolder.textView = (TextView) convertView.findViewById(R.id.text);
            convertView.setTag(viewHolder);
 
            // лисенер достаточно определить один раз для каждого холдера - при его создании
            viewHolder.button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {               
               View rootView = (View) v.getParent();
                TextView txt = (TextView) rootView.findViewById(R.id.text);
                txt.setText("OK");
               pressedPositions.put(position);
            }
        });
 
 
        }else{
            viewHolder = (ViewHolder) convertView.getTag();
            // проверяем нажата ли позиция
            if (!pressedPositions.contains(position)){
                // если не нажата - ставим нужный текст - не знаю какой, но пусть будет так для примера:
                viewHolder.textView.setText(items.get(position));
            }    
        }
        
        return convertView;
    }
    static class ViewHolder{
        Button button;
        TextView textView;
    }
}
В работе не пробовал, но думаю суть понятна.
Yandex
Объявления
03.02.2015, 23:19     Не понятное поведение BaseAdapter
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru