ListView установка Background у определенны элементов списка

Интерфейс, диалоги, темы, стили, меню
Ответить
KleverinD
Сообщения: 12
Зарегистрирован: 18 сен 2015, 20:45

ListView установка Background у определенны элементов списка

Сообщение KleverinD » 18 сен 2015, 21:00

Привествую

Подскажите пожалуйста как можно установить цвет фона некоторых элементов списка, конкретно сейчас нужно подкрашивать текущую дату в списке-календаре.
Способ через определение своего адаптера реализовал:

public class MySimpleAdapter extends SimpleAdapter
{
...
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
...
}
...
}

но список начал притормаживать, есть ли способ попроще, к примеру как то использовать <selector>? изучаю андроид недавно не могу разобраться.

Аватара пользователя
Mikhail_dev
Сообщения: 2386
Зарегистрирован: 09 янв 2012, 14:45
Откуда: Самара

Re: ListView установка Background у определенны элементов сп

Сообщение Mikhail_dev » 18 сен 2015, 23:22

Ну вообще нет, другого способа нету. А что у вас там притормаживает? Почему вы считаете что из-за этого? И как вы собственно реализовали это через адаптер? А то кода как бы и нету

KleverinD
Сообщения: 12
Зарегистрирован: 18 сен 2015, 20:45

Re: ListView установка Background у определенны элементов сп

Сообщение KleverinD » 20 сен 2015, 19:36

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

Код: Выделить всё

public class MySimpleAdapter extends SimpleAdapter
{
    private Context _ppt_context;
    private int _ppt_layoutResourceId;
    private ArrayList<Map<String, Object>> _ppt_items;
    private LayoutInflater _ppt_lif;

    public MySimpleAdapter(Context context, ArrayList<Map<String, Object>> items, int resource, String[] from, int[] to)
    {
        super(context, items, resource, from, to);

        _ppt_context = context;
        _ppt_layoutResourceId = resource;
        _ppt_items = items;

        _ppt_lif = ((Activity) _ppt_context).getLayoutInflater();
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
        DayHolder loc_holder;
        View  loc_row = _ppt_lif.inflate(_ppt_layoutResourceId, parent, false);

        loc_holder = new DayHolder();
        loc_holder.dev_itld_textview_date = (TextView)loc_row.findViewById(R.id.dev_itld_textview_date);
        loc_holder.dev_itld_textview_day_of_week = (TextView)loc_row.findViewById(R.id.dev_itld_textview_day_of_week);
        loc_holder.dev_itld_textview_event_count = (TextView)loc_row.findViewById(R.id.dev_itld_textview_event_count);
        loc_holder.dev_itld_textview_is_current_day = (TextView)loc_row.findViewById(R.id.dev_itld_textview_is_current_day);

        loc_row.setTag(loc_holder);

        Map<String, Object> loc_rowdata = _ppt_items.get(position);
        loc_holder.dev_itld_textview_is_current_day.setText(loc_rowdata.get("day_type").toString());
        loc_holder.dev_itld_textview_event_count.setText(loc_rowdata.get("event_count").toString());
        loc_holder.dev_itld_textview_day_of_week.setText(loc_rowdata.get("day_of_week").toString());
        loc_holder.dev_itld_textview_date.setText(loc_rowdata.get("date").toString());

        String loc_s = loc_rowdata.get("day_type").toString();
        if (loc_s.equals("1"))
            loc_row.setBackgroundColor(Color.GREEN);

        return loc_row;
    }

    static class DayHolder
    {
        TextView dev_itld_textview_is_current_day;
        TextView dev_itld_textview_date;
        TextView dev_itld_textview_day_of_week;
        TextView dev_itld_textview_event_count;
    }
}

Аватара пользователя
Mikhail_dev
Сообщения: 2386
Зарегистрирован: 09 янв 2012, 14:45
Откуда: Самара

Re: ListView установка Background у определенны элементов сп

Сообщение Mikhail_dev » 20 сен 2015, 20:16

У вас неправильно используются вьюшки для адаптера, они создаются везде. конечно список будет тормозить. Надо из переиспользовать. Вы верно начали использовать паттерн ViewHolder (или просто скопипастили правильный код), но надо так
[syntax=java]
public class MySimpleAdapter extends SimpleAdapter
{
private Context _ppt_context;
private int _ppt_layoutResourceId;
private ArrayList<Map<String, Object>> _ppt_items;
private LayoutInflater _ppt_lif;

public MySimpleAdapter(Context context, ArrayList<Map<String, Object>> items, int resource, String[] from, int[] to)
{
super(context, items, resource, from, to);

_ppt_context = context;
_ppt_layoutResourceId = resource;
_ppt_items = items;

_ppt_lif = ((Activity) _ppt_context).getLayoutInflater();
}

@Override
public View getView(int position, View convertView, ViewGroup parent)
{
DayHolder loc_holder;
if (convertView==null) {
View loc_row = _ppt_lif.inflate(_ppt_layoutResourceId, parent, false);

loc_holder = new DayHolder();
loc_holder.dev_itld_textview_date = (TextView)loc_row.findViewById(R.id.dev_itld_textview_date);
loc_holder.dev_itld_textview_day_of_week = (TextView)loc_row.findViewById(R.id.dev_itld_textview_day_of_week);
loc_holder.dev_itld_textview_event_count = (TextView)loc_row.findViewById(R.id.dev_itld_textview_event_count);
loc_holder.dev_itld_textview_is_current_day = (TextView)loc_row.findViewById(R.id.dev_itld_textview_is_current_day);
loc_row.setTag(loc_holder);
} else {
loc_holder = (DayHolder ) convertView.getTag();
}
Map<String, Object> loc_rowdata = _ppt_items.get(position);
loc_holder.dev_itld_textview_is_current_day.setText(loc_rowdata.get("day_type").toString());
loc_holder.dev_itld_textview_event_count.setText(loc_rowdata.get("event_count").toString());
loc_holder.dev_itld_textview_day_of_week.setText(loc_rowdata.get("day_of_week").toString());
loc_holder.dev_itld_textview_date.setText(loc_rowdata.get("date").toString());

String loc_s = loc_rowdata.get("day_type").toString();
if (loc_s.equals("1"))
loc_row.setBackgroundColor(Color.GREEN);

return loc_row;
}

static class DayHolder
{
TextView dev_itld_textview_is_current_day;
TextView dev_itld_textview_date;
TextView dev_itld_textview_day_of_week;
TextView dev_itld_textview_event_count;
}
}
[/syntax]

KleverinD
Сообщения: 12
Зарегистрирован: 18 сен 2015, 20:45

Re: ListView установка Background у определенны элементов сп

Сообщение KleverinD » 20 сен 2015, 20:45

я использовал чужой код как основу.
немного переписал код ваш пример и добавил строку
loc_row = super.getView(position, convertView, parent); если convertView != null т.к. функция возвращает loc_row, верно ли я сделал?

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

если ставить брекпоинт на строке
loc_row.setBackgroundColor(Color.GREEN);
в дэбаг режиме отлавливается только для одной строки (данные которой и помечены как текущая дата) а закрашивается несколько строк



[syntax=java]
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
View loc_row;
DayHolder loc_holder;

if (convertView == null)
{
loc_row = _ppt_lif.inflate(_ppt_layoutResourceId, parent, false);

loc_holder = new DayHolder();
loc_holder.dev_itld_textview_date = (TextView) loc_row.findViewById(_ppt_dev_itld_textview_date_id);
loc_holder.dev_itld_textview_day_of_week = (TextView) loc_row.findViewById(_ppt_dev_itld_textview_day_of_week_id);
loc_holder.dev_itld_textview_event_count = (TextView) loc_row.findViewById(_ppt_dev_itld_textview_event_count_id);
loc_holder.dev_itld_textview_is_current_day = (TextView) loc_row.findViewById(_ppt_dev_itld_textview_is_current_day_id);

loc_row.setTag(loc_holder);
}
else
{
loc_row = super.getView(position, convertView, parent);
loc_holder = (DayHolder)convertView.getTag();
}

Map<String, Object> loc_rowdata = _ppt_items.get(position);
String loc_s = loc_rowdata.get("day_type").toString();
loc_holder.dev_itld_textview_is_current_day.setText(loc_s);
loc_holder.dev_itld_textview_event_count.setText(loc_rowdata.get("event_count").toString());
loc_holder.dev_itld_textview_day_of_week.setText(loc_rowdata.get("day_of_week").toString());
loc_holder.dev_itld_textview_date.setText(loc_rowdata.get("date").toString());

if (loc_s.equals("1"))
loc_row.setBackgroundColor(Color.GREEN);

return loc_row;
}
[/syntax]

Аватара пользователя
doter.ua
Сообщения: 1106
Зарегистрирован: 23 ноя 2013, 16:08
Откуда: Ukraine

Re: ListView установка Background у определенны элементов сп

Сообщение doter.ua » 20 сен 2015, 21:18

super.getView(position, convertView, parent); вызовет метод родительского класса, с какой целью ты это делаешь?
Семь раз отмерь - поставь студию.
Эклипс не студия, ошибка вылетит - не исправишь.
Скажи мне кто твой друг, и оба поставили студию.
Студия - свет, а эклипс - тьма.

Аватара пользователя
Mikhail_dev
Сообщения: 2386
Зарегистрирован: 09 янв 2012, 14:45
Откуда: Самара

Re: ListView установка Background у определенны элементов сп

Сообщение Mikhail_dev » 21 сен 2015, 00:00

Плюсую комментарию doter.ua. Зачем это делать?

Этот код
[syntax=java]
if (loc_s.equals("1"))
loc_row.setBackgroundColor(Color.GREEN);
[/syntax]
заменить на
[syntax=java]
if (loc_s.equals("1"))
loc_row.setBackgroundColor(Color.GREEN);
else
loc_row.setBackgroundColor(your_color)
[/syntax]

KleverinD
Сообщения: 12
Зарегистрирован: 18 сен 2015, 20:45

Re: ListView установка Background у определенны элементов сп

Сообщение KleverinD » 21 сен 2015, 16:38

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

я так понял что метод getView видимо вызывает какой-то "диспетчер активити" который отрисовывает активити на экране и этот метод обязательно должен возвратить view для элемента списка. если convertView != null значит view для элементе списка уже был создан ранее и можно его и вернуть, иначе нужно создать view.

у меня метод возвращал loc_row
строкой loc_row = super.getView(position, convertView, parent); я просто в loc_row помещал уже созданный view, хотя как я понял можно было просто написать loc_row = convertView;

переделал метод так, теперь не тормозит

[syntax=java]
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
DayHolder loc_holder;

if (convertView == null)
{
convertView = _ppt_lif.inflate(_ppt_layoutResourceId, parent, false);

loc_holder = new DayHolder();
loc_holder.dev_itld_textview_date = (TextView) convertView.findViewById(_ppt_dev_itld_textview_date_id);
loc_holder.dev_itld_textview_day_of_week = (TextView) convertView.findViewById(_ppt_dev_itld_textview_day_of_week_id);
loc_holder.dev_itld_textview_event_count = (TextView) convertView.findViewById(_ppt_dev_itld_textview_event_count_id);
loc_holder.dev_itld_textview_is_current_day = (TextView) convertView.findViewById(_ppt_dev_itld_textview_is_current_day_id);

convertView.setTag(loc_holder);
}
else
{
loc_holder = (DayHolder)convertView.getTag();
}

Map<String, Object> loc_rowdata = _ppt_items.get(position);
String loc_s = loc_rowdata.get("day_type").toString();
loc_holder.dev_itld_textview_is_current_day.setText(loc_s);
loc_holder.dev_itld_textview_event_count.setText(loc_rowdata.get("event_count").toString());
loc_holder.dev_itld_textview_day_of_week.setText(loc_rowdata.get("day_of_week").toString());
loc_holder.dev_itld_textview_date.setText(loc_rowdata.get("date").toString());

if (loc_s.equals("1"))
convertView.setBackgroundColor(Color.GREEN);
else
convertView.setBackgroundColor(Color.GRAY);

return convertView;
}
[/syntax]

но осталось для меня не понятным если явно не указывать convertView.setBackgroundColor(Color.GRAY); то все таки фон нескольких элементов списка закрашивается зеленым. как так? ведь если view уже был создан ранее и его фон не бы установлен в зеленый почему он зеленым становится?

Аватара пользователя
doter.ua
Сообщения: 1106
Зарегистрирован: 23 ноя 2013, 16:08
Откуда: Ukraine

Re: ListView установка Background у определенны элементов сп

Сообщение doter.ua » 21 сен 2015, 18:47

Все условия должны основываться на входных данных. Если это ArrayAdapter то на данных элемента списка.
SomeClass item = getItem(position);
иф ( item.свойство == что_то ) {
//doSomething
}
Т.е. вью может использоваться по несколько раз, а вот данные всегда обновляются в соответствии с позицией.
Семь раз отмерь - поставь студию.
Эклипс не студия, ошибка вылетит - не исправишь.
Скажи мне кто твой друг, и оба поставили студию.
Студия - свет, а эклипс - тьма.

Аватара пользователя
Mikhail_dev
Сообщения: 2386
Зарегистрирован: 09 янв 2012, 14:45
Откуда: Самара

Re: ListView установка Background у определенны элементов сп

Сообщение Mikhail_dev » 21 сен 2015, 22:36

но осталось для меня не понятным если явно не указывать convertView.setBackgroundColor(Color.GRAY); то все таки фон нескольких элементов списка закрашивается зеленым. как так? ведь если view уже был создан ранее и его фон не бы установлен в зеленый почему он зеленым становится?
Для меня тоже загадка как это происходит. Возможно андроиду так проще создать объект, что вряд ли. Сам хотел бы услышать
Т.е. вью может использоваться по несколько раз, а вот данные всегда обновляются в соответствии с позицией.
Не совсем понятно как вью может использоваться по несколько раз. Вот к примеру у меня первый элемент списка с нажатыми checkbox (сам нажал), а потом спускаюсь вниз и вижу что седьмой элемент также нажат. Я отжал эти чекбоксы, но первый элемент списка ведь не изменился. Собственно вопрос: что, черт возьми, творится?

Аватара пользователя
doter.ua
Сообщения: 1106
Зарегистрирован: 23 ноя 2013, 16:08
Откуда: Ukraine

Re: ListView установка Background у определенны элементов сп

Сообщение doter.ua » 21 сен 2015, 23:13

Кароче нужно проставить свойства\флаги так, как будто вью создается первый раз. Т.е. если есть чекбокс, то ему нужно установить состояние, используя инфу из item. Грубо говоря при запуске все чекбоксы unChecked и свойство isChecked всех итемов = false, н омы все равно будем явно задавать
myCheckBox.setIsChecked( item.isChecked() );

Ведроид хранит столько инстансов вью, сколько хватит чтобы заполнить весь экран. Т.е. если элементов 10 000, а на экране влезает 10, то будет хранить 10. Вот ссыль почитать http://stackoverflow.com/a/14108676
Семь раз отмерь - поставь студию.
Эклипс не студия, ошибка вылетит - не исправишь.
Скажи мне кто твой друг, и оба поставили студию.
Студия - свет, а эклипс - тьма.

Аватара пользователя
Mikhail_dev
Сообщения: 2386
Зарегистрирован: 09 янв 2012, 14:45
Откуда: Самара

Re: ListView установка Background у определенны элементов сп

Сообщение Mikhail_dev » 22 сен 2015, 12:15

Грубо говоря при запуске все чекбоксы unChecked и свойство isChecked всех итемов = false
У меня такое не получится. Суть в том, что при клике на checkBox, я запускаю notifyChanged, чтобы обновились вьюшки. У меня такая структура
Изображение
Если кликнуть по первому чекбоксу, то становится доступным второй чекбокс, если кликаю по второму, то становится доступным первый следующего элемента. Если мне при старте выставлять все чекбоксы в false, то они никогда не нажмутся, потому что будут сбрасываться.

Я сделал по похожему сценарию. Я просто не трогаю уже нажатые чекбоксы, а те что вверху всегда перевожу в false. Но может как попроще можно решить проблему?

Аватара пользователя
Foenix
Сообщения: 4201
Зарегистрирован: 20 окт 2012, 12:01

Re: ListView установка Background у определенны элементов сп

Сообщение Foenix » 22 сен 2015, 14:54

KleverinD писал(а):спасибо господа, для меня вроде начинает проясняться, проэкзаменуйте меня еще )

я так понял что метод getView видимо вызывает какой-то "диспетчер активити" который отрисовывает активити на экране и этот метод обязательно должен возвратить view для элемента списка. если convertView != null значит view для элементе списка уже был создан ранее и можно его и вернуть, иначе нужно создать view.


но осталось для меня не понятным если явно не указывать convertView.setBackgroundColor(Color.GRAY); то все таки фон нескольких элементов списка закрашивается зеленым. как так? ведь если view уже был создан ранее и его фон не бы установлен в зеленый почему он зеленым становится?
http://stackoverflow.com/questions/1194 ... nism-works
Потому что вьюшки не хранятся а отдаются ресайклеру
См тут первый ответ
R.id.team

NullPointerException - что делать???
viewtopic.php?f=33&t=3899&p=28952#p28952
Где моя ошибка?
viewtopic.php?f=60&t=3198

Аватара пользователя
doter.ua
Сообщения: 1106
Зарегистрирован: 23 ноя 2013, 16:08
Откуда: Ukraine

Re: ListView установка Background у определенны элементов сп

Сообщение doter.ua » 22 сен 2015, 15:07

Чекбоксы не выступают в качестве хранителей информации, это просто вью которое может отобразить галочку. любой интерактив должен изменять item. Следовательно доступность элементов определяется состоянием полей item-а с индексом "текущий - 1".
Значения полей item-а не зависят от внутренних механизмов адаптера.
Семь раз отмерь - поставь студию.
Эклипс не студия, ошибка вылетит - не исправишь.
Скажи мне кто твой друг, и оба поставили студию.
Студия - свет, а эклипс - тьма.

Ответить