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

Не понятное поведение BaseAdapter - Android

Войти
Регистрация
Восстановить пароль
 
Sleep37
4 / 4 / 1
Регистрация: 06.01.2013
Сообщений: 16
12.08.2014, 11:51     Не понятное поведение BaseAdapter #1
Добрый день!
Проблема в следующем: есть 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
Посмотрите здесь:

Android При клики в BaseAdapter меняется массив строк, как пересоздать ListView с новым массивом?
Непонятное поведение ArrayList Android
Android Анимация ViewGroup, некорректное поведение кнопки
BaseAdapter Android
Как вывести в BaseAdapter картинки, занесенные в таблицу? Android
Android Поведение после смены ориентации экрана
Неадекватное поведение адаптера ListView Android
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
YuraAAA
 Аватар для YuraAAA
1563 / 1305 / 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
210 / 210 / 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
 Аватар для 646kapeh064
59 / 58 / 15
Регистрация: 09.12.2013
Сообщений: 208
14.08.2014, 00:16     Не понятное поведение BaseAdapter #6
Sleep37, потому-что элементы списка пересоздаются (невидимые элементы удаляются, чтоб не загружать память мусором).
Храни например в своём ViewHolder введенный текст в текстовое поле.
NiRamz
210 / 210 / 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
Еще ссылки по теме:

Android Непонятное поведение программы!
Android Sockets и потоки, разное поведение на устройствах
Android Не вижу абстрактных методов в классе BaseAdapter
Android Непонятное поведение многопоточного приложения
Android BaseAdapter

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

Или воспользуйтесь поиском по форуму:
kvaka
 Аватар для 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
Ответ Создать тему
Опции темы

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