Usually we need to update item in GridView programmatically without using “ClickListener”. Instead, we can set a “selected position” variable in our Adapter and do position matching in getView(). Usually, our code will end-up like this:
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 | public void setChoosenDate(int date) { this.selectedDate = date; } @Override public View getView(int position, View convertView, ViewGroup parent) { View v = convertView; ViewHolder holder; // to reference the child views for later actions if(convertView == null) { LayoutInflater inflater = (LayoutInflater) mContext .getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.item, null); // cache view fields into the holder holder = new ViewHolder(); …. } else { holder = (ViewHolder) convertView.getTag(); if(this.selectedDate != null && position == this.selectedDate) { Log.d(LOG_TAG, "Selected position : " + position); // Set text resource on each position convertView.setBackgroundColor(Color.BLACK); Log.d(LOG_TAG, "Selected position : " + convertView.getId()); } } return convertView; } |
We see at this line :
1 | this.selectedDate != null && position == this.selectedDate |
That’s mean we compare the selectedDate that set by the users and the position of View that shown by users. Unfortunately, this will lead to problem which this will get more than 2 cells will have updated background into Black. This is some screenshot:
Based on the log results, all is correct:
1 2 3 4 5 6 7 8 9 | 12-16 16:05:26.539: D/ANDROID(12415): Position: 2 12-16 16:05:27.289: D/ANDROID(12415): Position: 12 12-16 16:05:27.299: D/ANDROID(12415): Position: 13 12-16 16:05:27.299: D/ANDROID(12415): Position: 14 12-16 16:05:27.889: D/ANDROID(12415): Selected position : 15 12-16 16:05:27.889: D/ANDROID(12415): Selected position : 2131165196 12-16 16:05:27.889: D/ANDROID(12415): Position: 15 12-16 16:05:27.899: D/ANDROID(12415): Position: 16 12-16 16:05:27.899: D/ANDROID(12415): Position: 17 |
Is that because we don’t put adapter.invalidateView() ? Well, this method will called automatically anyway, so we don’t need to re-declare it.
Then, what’s the solution?
The solution is by FORCE all the cells into default background color, when one cells background updated. So this is the implementation:
1 2 3 4 5 6 7 8 9 | if(this.selectedDate != null && position == this.selectedDate) { Log.d(LOG_TAG, "Selected position : " + position); // Set text resource on each position convertView.setBackgroundColor(Color.BLACK); Log.d(LOG_TAG, "Selected position : " + convertView.getId()); } else { convertView.setBackgroundColor(Color.WHITE); } |
Then the results will be like this: