Jesusrz001 Jesusrz001 - 1 month ago 18
Android Question

Prevent the adapter from recycling views on scroll

I have a custom base adapter that will take in an arraylist of data. From here it will fill out a grid view with custom buttons. It does so perfectly and fills up the gridview. The problem is. I want to set a button to change colors on change. When I do this, since the view is recycled, it also changes the next view that is recycled. Ex. Click on button one at position 0. Also changes button at position 13. Now when I do some debugging, I find that it also changes some of the properties. I am wondering if there is anyway of creating my view as it is without needing to recycle any part of the views.

I have seen some things about using stableID's but even when I have overridden it to true. It still does not currently change it.

static class CategoryButtonAdapter extends BaseAdapter
{
private Context mContext;
private ArrayList<DishCategory> dishCategories;
private ArrayList<Dish> dishItems;
static ArrayList<DishCategoryButton> mDishCategoryButtons;
//will take in an array list created in the orderlayout that will be the
//dish category. This will be the from where we will the count for the adapter
public CategoryButtonAdapter(Context context, ArrayList<DishCategory> dishCategories)
{
this.mContext = context;
this.dishCategories = dishCategories;

dishItems = dishCategories.get(0).getDishes();
}

public int getCount()
{
return dishCategories.size();
}

//to be implementated later so it can b3e used to find menu categories
@Override
public DishCategory getItem(int position)
{
return dishCategories.get(position);
}

public void getDishCategoryButtons()
{
if(mDishCategoryButtons.size() == 0)
{
System.out.println("The number of buttons in this adapapter is " + mDishCategoryButtons.size());
}
else
{
System.out.println("The number of buttons in this adapapter is " + mDishCategoryButtons.size());
}
}

public long getItemId(int position)
{
return dishCategories.get(position).getDishCategoryID();
}

@Override
public boolean hasStableIds() {
//return super.hasStableIds(); //To change body of generated methods, choose Tools | Templates.
return true;
}

public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder;
DishCategoryButton button = null;
//button to be created
if(convertView == null )
{
holder = new ViewHolder();
//if it is not recycled, initialize some new attributes
button = new DishCategoryButton(this.mContext,dishCategories.get(position));
button.setLayoutParams(new GridView.LayoutParams(100,100));
button.setPadding(2,2,2,2);
//convertView.setTag(holder);
button.setTag(holder);
}
else
{
//holder = (ViewHolder)convertView.getTag();
button = (DishCategoryButton) convertView;
}
//setButton to the description of the category
//mDishCategoryButtons.add(button);
button.setText((dishCategories.get(position).getDescription()));
//this can be changed later to change the sex appeal of the app
//for now it will be plain
button.setId(position);

//.setOnClickListener(new View.OnClickListener()
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Perform action on click
DishCategoryButton dishCategoryButton = (DishCategoryButton)v;
PaintDrawable drawable = (PaintDrawable) dishCategoryButton.getBackground();
System.out.println("Dish button position is " + dishCategoryButton.getId());
//System.out.println("The position from the array says it is at " + position);
System.out.println("Dish Category is " + dishCategoryButton.getDishCategory().getDescription());
System.out.println("Is it currently selected " + dishCategoryButton.getIsSelected());

int color = drawable.getPaint().getColor();
System.out.println("Color is " + color);
dishCategoryButton.setIsSelected(true);
drawable = (PaintDrawable) dishCategoryButton.getBackground();
color = drawable.getPaint().getColor();
System.out.println("Color is " + color);
System.out.println("hi");

// The toggle is enabled

}
});
//new loadDishItems(categoryButtons.get(position).getDescription()));
return button;
}


Don't worry about the view holder. that was an attempt to prevent the recycling. Any clues or ideas on how to get this?

Here is my button

public class DishCategoryButton extends Button
{
private DishCategory dishCategory = new DishCategory();
private Boolean isSelected = false;


public DishCategoryButton(Context context, DishCategory dishCategory)
{
super(context);
this.dishCategory = dishCategory;
isSelected = false;
setTextColor(Color.WHITE);
setBackgroundDrawable(new PaintDrawable(Color.BLACK));
}
public DishCategory getDishCategory()
{
return dishCategory;
}
public void setDishCategory(DishCategory dishCategory)
{
this.dishCategory = dishCategory;
}

public Boolean getIsSelected() {
return isSelected;
}

public void setIsSelected(Boolean isSelected) {
this.isSelected = isSelected;
if(isSelected == true)
{
setTextColor(Color.WHITE);
setBackgroundDrawable(new PaintDrawable(Color.GREEN));
}
else
{
setTextColor(Color.WHITE);
setBackgroundDrawable(new PaintDrawable(Color.BLACK));
}
}


}

Answer Source

Prevent the adapter from recycling views on scroll

Just don't use the convertView param passed to getView() and always return a freshly generated View.

However, this is a bad solution in terms of performance. Instead, your goal should not be to prevent recycling but to recycle correcltly: Your getView() should reset the convertView to it's pristine state.

So, if there's a change that some of your Button's properties are changed from their non-default values, reset them back to defaults in getView().