I have a ListFragment
that contains a TextView
and two Buttons in every item. Clicking on one Button
changes the background color of the list item and clicking on the other deletes the item from the list. Now, the background state of an item will be maintained as long as no scrolling occurs. Once the list becomes long enough to scroll, the background states / views of various items are recycled causing list items that were not clicked to have their background colors changed.
I am able to retain the state of the background by storing list item positions accessible in the
getView(int position, View convertView, ViewGroup parent)
method of the ListFragment's CustomAdapter
(a SimpleAdapter
in my case) in an ArrayList
and then checking if the ArrayList
contains a selected position just before the inflated view is returned. If the position exists in the ArrayList
then the background color of that item is set to green, else it is set to transparent. Here is my code:
@Override
public View getView(int position, View convertView, ViewGroup parent){
View view = convertView;
final int pos = position;
view = super.getView(position,convertView,parent);
Button buttonChangeBackground = (Button) view.findViewById(R.id.button_1);
buttonChangeBackground.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
View view =(View) v.getParent();
view.setBackgroundColor(Color.GREEN);
// storing list item positions in ArrayList
coloredItems.add(pos);
}
});
Button buttonDelete = (Button) view.findViewById(R.id.button_2);
buttonDelete.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
datalist.remove(pos);
notifyDataSetChanged();
}
});
/*
* Using the stored positions to retain background state.
*/
if(coloredItems.contains(pos))
view.setBackgroundColor(Color.GREEN);
else
view.setBackgroundColor(Color.TRANSPARENT);
return view;
}
This works as long as no item is deleted from the list. I understand that once a list item is deleted all items after and including the deleted item need to have their positions decremented by 1 in the ArrayList
so that states are maintained in their modified positions. I have tried many methods however I always throw an IndexOutOfBoundsException.
What code should I add to ensure that all list items retain their background state even after a list item is deleted ? This appears to be a simple ArrayList
manipulation problem
but I am unable to arrive at a solution.
Answering my question. This answer is based on the comment left by @pskink.
While creating the dataset for the adapter add an extra key that indicates the default background state of a list item and an appropriate value. In my case I used
map.add("BACKGROUND","BACKGROUND_PLAIN");
Now, in the getView method change the value of the key within the OnClickListener of the Button that changes the View's background. In my case:
Button buttonChangeBackground = (Button) view.findViewById(R.id.button_1);
buttonChangeBackground.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
// obtaining map associated with current data item's position.
final HashMap<String,String> map = datalist.get(pos);
// changing value associated with key.
map.put("BACKGROUND", "GREEN");
notifyDataSetChanged();
}
});
Now, just before the getView method returns check if the data item associated with the current view contains a modified value or the default value set for the background. If the value is modified, set background of view to green, else set the background to its default value, which is Color.Transparent in my case.
hashMap = datalist.get(position);
if(hashMap.containsValue("GREEN")){
view.setBackgroundColor(Color.GREEN);
}
else{
view.setBackgroundColor(Color.TRANSPARENT);
}
The full code:
@Override
public View getView(int position, View convertView, ViewGroup parent){
View view = convertView;
final int pos = position;
HashMap<String,String> hashMap = new HashMap<String,String>();
view = super.getView(position,convertView,parent);
Button buttonChangeBackground = (Button) view.findViewById(R.id.button_1);
buttonChangeBackground.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
// obtaining map associated with current data item's position.
final HashMap<String,String> map = datalist.get(pos);
// changing value associated with key.
map.put("BACKGROUND", "GREEN");
notifyDataSetChanged();
}
});
Button buttonDelete = (Button) view.findViewById(R.id.button_2);
buttonDelete.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
datalist.remove(pos);
notifyDataSetChanged();
}
});
hashMap = datalist.get(position);
if(hashMap.containsValue("GREEN")){
view.setBackgroundColor(Color.GREEN);
}
else{
view.setBackgroundColor(Color.TRANSPARENT);
}
return view;
}