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

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

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 10, средняя оценка - 4.70
Hedd
13 / 13 / 2
Регистрация: 21.01.2015
Сообщений: 131
#1

GridView. Изменение бекграунда по нажатию - Программирование Android

28.01.2015, 02:28. Просмотров 1422. Ответов 28
Метки нет (Все метки)

Есть элемент GridView, который я вызываю через Spinner.
По нажатию на один из элементов GridView, его background должен меняться на другой цвет и приложение вызывает ListView с данными из базы данных. Все действия происходят в одной Activity. Верхняя половина окна - Spinner+ GridView. Нижняя половина - ListView. БД формируется через отдельный класс.
Вызов данных работает отлично, список формируется, но цвет background у нажатого элемента GridView не меняется.
Операция по смене background прописана верно. Проверял в других приложениях. Что примечательно, цвет background меняется, если закоментировать строку с формированием списка ListView из бд.

В чем может быть проблема?

Так я ставлю бекграунд грида:
Java
1
2
3
4
5
6
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@color/background_selected" android:state_pressed="true"/>
    <item android:drawable="@color/background_selected" android:state_selected="true"/>
    <item android:drawable="@color/background_default" />
</selector>
Java
1
2
3
4
5
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="background_selected">#ffffff</color>
    <color name="background_default">#ffbe3f38</color>
</resources>
Java
1
2
3
4
5
 <GridView
        android:listSelector="@color/bg_days" 
        ....
        ....>
        </GridView>
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Armagedo
208 / 208 / 60
Регистрация: 22.08.2014
Сообщений: 644
28.01.2015, 10:26     GridView. Изменение бекграунда по нажатию #2
Можно предположить, что в момент, когда появляется ListView, то фокус уже не у GridView, который теперь и не pressed, и не selected.
Hedd
13 / 13 / 2
Регистрация: 21.01.2015
Сообщений: 131
28.01.2015, 10:29  [ТС]     GridView. Изменение бекграунда по нажатию #3
Armagedo, Есть идеи как это можно исправить?
Я думал, что конфликт из-за обращения к БД, но нет. Создал отдельное приложение с GridView и ListView. Заполнил ListView по нажатию по GridView обычным массивом String[], который задал в активити. Проблема осталась. фон не отмечается.
Armagedo
208 / 208 / 60
Регистрация: 22.08.2014
Сообщений: 644
28.01.2015, 10:59     GridView. Изменение бекграунда по нажатию #4
Программно, переписав метод getView() адаптера.
Вешать AdapterView.OnItemClickListener, отлавливать onClick(), получать позицию элемента грида и обновлять грид.

Добавлено через 15 минут
Идея начинается со слов "в лоб" тут Выбираются все пункты в RadioButton
Hedd
13 / 13 / 2
Регистрация: 21.01.2015
Сообщений: 131
28.01.2015, 12:33  [ТС]     GridView. Изменение бекграунда по нажатию #5
Armagedo, что то я немного запутался..
Идею с глобальной переменной вроде понял, но никак не могу додумать как реализовать 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
public class MainActivity extends ActionBarActivity {
    
    //массив для ListView
    String[] lvArray = {"1", "2", "3", "4", "5"};
    //массив для GridView
    String[] gvArray = {"1", "2", "3", "4", "5"};
 
    int checkedItemPosition = -1;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
      
      //GridView адаптер
      final  GridView gv = (GridView) findViewById(R.id.gridView1);
        final ArrayAdapter<String> gvadapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1, gvArray);
        gv.setAdapter(gvadapter);
        
      //нажатие на элемент GridView
        gv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
 
                if (checkedItemPosition != position)
                    checkedItemPosition = position;
                else checkedItemPosition = -1;
 
                gvadapter.notifyDataSetChanged();
 
                showListView();
            }
        });
 
    }
    
    //вызов ListView
    private void showListView() {
 
        final  ListView lv = (ListView) findViewById(R.id.lvMain);
        final ArrayAdapter<String> lvadapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1, lvArray);
        lv.setAdapter(lvadapter);
    }
Armagedo
208 / 208 / 60
Регистрация: 22.08.2014
Сообщений: 644
28.01.2015, 12:49     GridView. Изменение бекграунда по нажатию #6
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Java
1
2
3
4
5
6
7
8
9
10
11
12
final ArrayAdapter<String> gvadapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1, gvArray){
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
         
      View view = super.getView(position, convertView, parent);
 
        if (position==checkedItemPosition)
                                 view.setBackgroundColor(Color.YELLOW);
       
     return view;
};
Добавлено через 6 минут
Не, всё же метод супер-класса лучше отработать...
Hedd
13 / 13 / 2
Регистрация: 21.01.2015
Сообщений: 131
28.01.2015, 13:07  [ТС]     GridView. Изменение бекграунда по нажатию #7
Armagedo, Спасибо, разобрался! Все получилось. Так же добавил else, чтобы фон предыдущего нажатого элемента убирался, а не оставался.
Armagedo
208 / 208 / 60
Регистрация: 22.08.2014
Сообщений: 644
28.01.2015, 13:12     GridView. Изменение бекграунда по нажатию #8
Hedd, на здоровье
Hedd
13 / 13 / 2
Регистрация: 21.01.2015
Сообщений: 131
28.01.2015, 13:13  [ТС]     GridView. Изменение бекграунда по нажатию #9
Armagedo, Кстати, я могу в этом getView() каким то образом так же задать изменение цвета текста по выделению?
Armagedo
208 / 208 / 60
Регистрация: 22.08.2014
Сообщений: 644
28.01.2015, 13:25     GridView. Изменение бекграунда по нажатию #10
Дык, а че б и нет.

android.R.layout.simple_list_item_1 в себе содержит (два) TextView, для которых доступен метод setTextColor
Hedd
13 / 13 / 2
Регистрация: 21.01.2015
Сообщений: 131
28.01.2015, 13:27  [ТС]     GridView. Изменение бекграунда по нажатию #11
Цитата Сообщение от Hedd Посмотреть сообщение
Armagedo, Кстати, я могу в этом getView() каким то образом так же задать изменение цвета текста по выделению?
Вроде понял:
Java
1
2
TextView tv1 = (TextView)view.findViewById(android.R.id.text1);
tv1.SetTextColor(...);
Поправьте, если я не прав
Armagedo
208 / 208 / 60
Регистрация: 22.08.2014
Сообщений: 644
28.01.2015, 13:29     GridView. Изменение бекграунда по нажатию #12
Ну, да.
Hedd
13 / 13 / 2
Регистрация: 21.01.2015
Сообщений: 131
28.01.2015, 15:10  [ТС]     GridView. Изменение бекграунда по нажатию #13
Armagedo, Теперь столкнулся с другой проблемой, при попытке добавить функционал getView() в свой проект, описанный в первом посте.

Вставил код верно, проект компилируется, приложение запускается, но при нажатии на элемент GridView фон устанавливается только у любого первого нажатого элемента. При нажатии на другой элемент, фон остается на первом нажатом, а на новом нажатом элементе не меняется.
Если в спиннере выбрать другой пункт - GridView обновляется и можно выбрать другой элемент, опять же единожды.

Структура у моего приложения такова:
Spinner, в котором 4 пункта. По нажатию на каждый пункт отображается разный GridView с данными из БД.
GridView - состоит из 5 элементов, по нажатию на каждый пункт, отображается разный ListView с данными из БД.

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

Вот код моей Activity:
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
public class MainActivity extends Activity {
    
 //доступ к классу БД
    private ObjectsAdapter oDbHelper;
 
    private SimpleCursorAdapter oDataAdapter;
 
    public static int test;
    public static int test2;
 
    int checkedItemPosition = -1;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
 //Операции с БД при запуске приложения
        oDbHelper = new ObjectsAdapter(this);
        oDbHelper.open();
        oDbHelper.deleteAllObjects();
        oDbHelper.insertObjects();
 
 // Spinner
        ArrayAdapter<?> adapter =
                ArrayAdapter.createFromResource(this, R.array.weeksList, R.layout.spinner_item);
        adapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
        Spinner spinner = (Spinner) findViewById(R.id.spinner);
        spinner.setAdapter(adapter);
 
        spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
 
  //По нажатию на пункт спиннера выбирается соотв. GridView из БД.
  //где test - переменная для класса с БД для выбора данных 
                switch (position+1){
                    case 1: test = 1;  break;
                    case 2: test = 2;  break;
                    case 3: test = 3;  break;
                    case 4: test = 4;  break;
                    default: break;
                }
                
 // отображаем выбранные элементы GridView (описано ниже)
                displayDaysView();
            }
 
            @Override
            public void onNothingSelected(AdapterView<?> parent) {
 
            }
        });
    }
 
    private void displayDaysView() {
        Cursor cursor = oDbHelper.fetchAllDays();
 
        String[] columns = new String[] {
                ObjectsAdapter.KEY_DAY,
                ObjectsAdapter.KEY_DATE
        };
 
        int[] to = new int[] {
                R.id.tvDay,
                R.id.tvDate,
        };
 
 // Адаптер для GridView
        final GridView gvDays = (GridView) findViewById(R.id.gridView1);
        oDataAdapter = new SimpleCursorAdapter(
                this, R.layout.list_days_items, cursor, columns, to, 0){
 
            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
 
                View view = super.getView(position, convertView, parent);
 
                TextView tvDay = (TextView) view.findViewById(R.id.tvDay);
                TextView tvDate = (TextView) view.findViewById(R.id.tvDate);
 
                if (position == checkedItemPosition) {
                    view.setBackgroundColor(Color.YELLOW);
                tvDay.setTextColor(Color.WHITE);
                tvDate.setTextColor(Color.WHITE); }
                else {view.setBackgroundColor(Color.TRANSPARENT);
                tvDay.setTextColor(Color.BLACK);
                tvDate.setTextColor(Color.GRAY); }
                return view;
            };
        };
 
        gvDays.setAdapter(oDataAdapter);
 
        gvDays.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
 
                if (checkedItemPosition != position)
                    checkedItemPosition = position;
                else checkedItemPosition = -1;
 
                oDataAdapter.notifyDataSetChanged();
 
// по нажатию на элемент GridView получаем id нажатого элемента из БД.
//где test2 - переменная из класса БД для выборки данных.
                Cursor cursor = (Cursor) gvDays.getItemAtPosition(position);
                String objectsId = cursor.getString(cursor.getColumnIndexOrThrow("_id"));
 
                switch (objectsId) {
                    case "1": test2 = 1; break;
                    case "4": test2 = 4; break;
                    case "8": test2 = 8; break;
                    case "11": test2 = 11; break;
                    case "14": test2 = 14; break;
                }
 //заполняем ListView соответств. данными из БД
                displayObjectsView();
            }
        });
    }
 
 
    private void displayObjectsView() {
        Cursor cursor = oDbHelper.fetchAllObjects();
 
        String[] columns = new String[] {
                ObjectsAdapter.KEY_OBJECT,
                ObjectsAdapter.KEY_TYPE,
                ObjectsAdapter.KEY_PLACE,
                ObjectsAdapter.KEY_TIMESTART,
                ObjectsAdapter.KEY_TIMEFINISH,
                ObjectsAdapter.KEY_TEACHER
        };
 
        int[] to = new int[] {
                R.id.objects_object,
                R.id.objects_type,
                R.id.objects_place,
                R.id.objects_timestart,
                R.id.objects_timefinish,
                R.id.objects_teacher,
        };
 
        oDataAdapter = new SimpleCursorAdapter(
                this, R.layout.list_objects_items, cursor, columns, to, 0);
 
        final ListView lvObjects = (ListView) findViewById(R.id.lvMain);
        lvObjects.setAdapter(oDataAdapter);
    }
}
Armagedo
208 / 208 / 60
Регистрация: 22.08.2014
Сообщений: 644
28.01.2015, 17:11     GridView. Изменение бекграунда по нажатию #14
Как-то всё запутано у вас в коде...тяжело сходу разбираться...

Почему переменная под адаптер oDataAdapter инициализируется, как адаптер и для грида и для листвью?
Вас это не смущает?

Зачем у вас при каждом клике создаются новые адаптеры гридвью и потом листвью?
Чем они, адаптеры, принципиально отличаются от ранее созданных.

Создайте два разных адаптера.
Прицепите эти адаптеры единожды соответственно к гридвью и листвью.
Делайте выборки в нужные курсоры - источники данных для гридвью и листвью.

Меняйте источники данных для адаптеров через mAdapter.changeCursor(newursor);

И сообщайте, что данные изменились через mAdapter.notifyDataSetChanged();
Hedd
13 / 13 / 2
Регистрация: 21.01.2015
Сообщений: 131
28.01.2015, 18:23  [ТС]     GridView. Изменение бекграунда по нажатию #15
Armagedo, Действительно, как то я не заметил, что после очередного редактирования один адаптер создал для двух View. Моя ошибка, спасибо. Создал второй адаптер, фон стал меняться корректно.
А как то можно закрепить нажатый элемент?
Т.е. если я опять щелкну по тому же элементу, его фон обратно станет начального цвета.

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

И еще, я как то могу сбросить ListView после вызова из спиннера нового GridView? Сейчас, если я выбираю другой грид через спиннер, данные с предыдыдущего ListView висят на экране, пока я не нажму по элементу грида нововызванного
Armagedo
208 / 208 / 60
Регистрация: 22.08.2014
Сообщений: 644
28.01.2015, 18:57     GridView. Изменение бекграунда по нажатию #16
Цитата Сообщение от Hedd Посмотреть сообщение
А как то можно закрепить нажатый элемент?
Т.е. если я опять щелкну по тому же элементу, его фон обратно станет начального цвета.
Уберите
else checkedItemPosition = -1;
Цитата Сообщение от Hedd Посмотреть сообщение
И еще, я как то могу сбросить ListView после вызова из спиннера нового GridView? Сейчас, если я выбираю другой грид через спиннер, данные с предыдыдущего ListView висят на экране, пока я не нажму по элементу грида нововызванного
В выборе элемента спиннера

Java
1
2
mListViewAdapter.changeCursor(null);
mListViewAdapter.notifyDataSetChanged();
Hedd
13 / 13 / 2
Регистрация: 21.01.2015
Сообщений: 131
28.01.2015, 19:23  [ТС]     GridView. Изменение бекграунда по нажатию #17
Armagedo, С фоном разобрался. Спасибо!
ListView удалось сбросить, но только во всех элементах, кроме первого. Если ставить для первого, то приложение закрывается с NullException, что логично, так как сбрасывать нечего. Как этого избежать?

Либо есть еще идея, при выборе другого GridView автоматически включать ListView с позиции первого элемента GridView. Только не знаю как реализовать. Может как то через cursor.moveToFirst.. но не уверен, что так можно..
Armagedo
208 / 208 / 60
Регистрация: 22.08.2014
Сообщений: 644
28.01.2015, 19:30     GridView. Изменение бекграунда по нажатию #18
Цитата Сообщение от Hedd Посмотреть сообщение
ListView удалось сбросить, но только во всех элементах, кроме первого. Если ставить для первого, то приложение закрывается с NullException, что логично, так как сбрасывать нечего. Как этого избежать?
для какого "первого"?

Выкладывайте код.
Hedd
13 / 13 / 2
Регистрация: 21.01.2015
Сообщений: 131
28.01.2015, 19:41  [ТС]     GridView. Изменение бекграунда по нажатию #19
Armagedo, ну, если оставить все как было, то у меня же по умолчанию, при запуске приложения, первый пункт спиннера нажат и, соответственный ему GridView показан на экране.
Кликните здесь для просмотра всего текста
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
 // Spinner
        ArrayAdapter<?> adapter =
                ArrayAdapter.createFromResource(this, R.array.weeksList, R.layout.spinner_item);
        adapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
        Spinner spinner = (Spinner) findViewById(R.id.spinner);
        spinner.setAdapter(adapter);
 
        spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
 
 
                switch (position+1){
                    case 1: test = 1;  break;
                    case 2: test = 2;  break;
                    case 3: test = 3;  break;
                    case 4: test = 4;  break;
                    default: break;
                }
 
                ListAdapter.changeCursor(null);
                ListAdapter.notifyDataSetChanged();
 
                displayDaysView();
            }
 
            @Override
            public void onNothingSelected(AdapterView<?> parent) {
 
            }
        });
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
28.01.2015, 20:01     GridView. Изменение бекграунда по нажатию
Еще ссылки по теме:
Android NavigationView с GridView
GridView и ViewPager Android
Android Разметка GridView
Android Не перерисовывается GridView
Android Обновление gridView

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

Или воспользуйтесь поиском по форуму:
Armagedo
208 / 208 / 60
Регистрация: 22.08.2014
Сообщений: 644
28.01.2015, 20:01     GridView. Изменение бекграунда по нажатию #20
ВЕСЬ код вашего класса Activity давайте

Кстати, что это у вас за хитрый код такой для выражения
Java
1
test = position +1
Yandex
Объявления
28.01.2015, 20:01     GridView. Изменение бекграунда по нажатию
Ответ Создать тему
Опции темы

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