9

In last week, i just try to resolve this problem. see every similar questions and i don't know why, solutions don't work for me. I have a list view and each item has an image view. when clicked on image view , i want to change image resource. well. all done. but when scrolling, image resources change. my full code is:

public class CustomBaseAdapter extends BaseAdapter {

Context context;
ArrayList<String> items;

    public CustomBaseAdapter(Context context,ArrayList<String> items){
        this.context = context;
        this.items = items;
    }

private class ViewHolder{
    TextView titr;
    ImageView image;
}

@Override
public int getCount() {
    return items.size();
}

@Override
public Object getItem(int position) {
    return items.get(position);
}

@Override
public long getItemId(int position) {
    return items.hashCode();
}

@Override
public View getView(int position, View view, ViewGroup parent) {
    View vi = view;
    final ViewHolder holder ;
    LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    if(view==null){

        vi = inflater.inflate(R.layout.customlistitem,null);
        holder = new ViewHolder();
        holder.titr = (TextView) vi.findViewById(R.id.listtext);
        holder.image = (ImageView) vi.findViewById(R.id.listimg);
        holder.image.setTag(position);
        vi.setTag(holder);
    }
    else{
        holder = (ViewHolder) vi.getTag();
    }


    holder.titr.setText(items.get(position));

    holder.image.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
           v.setBackgroundResource(R.drawable.fav_ic);
        }
    });
    return vi;
}

}

where i have mistake?

Sadeq Shajary
  • 427
  • 6
  • 17

5 Answers5

6

you have to use one boolean value in holder to check whether your background image is set or not for particular row.

holder

private class ViewHolder{
    TextView titr;
    ImageView image;
boolean isSet;
}

set image

holder.image.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
           v.setBackgroundResource(R.drawable.fav_ic);
holder.isSet = true
        }
    });

if(holder.isSet)
 {
holder.image.setBackgroundResource(R.drawable.fav_ic);
}
else{
holder.image.setBackgroundResource(no image or other image);
}

hope this will help.

KDeogharkar
  • 10,939
  • 7
  • 51
  • 95
2

This is because when you scroll listview android system always create new row and destroy non-visible rows. You need to modify the getView() as below then everything will be fine :

@Override
public View getView(int position, View view, ViewGroup parent) {
    View vi = view;
    final ViewHolder holder ;
    LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

SharedPreferences sp  = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());

    if(view==null){

        vi = inflater.inflate(R.layout.customlistitem,null);
        holder = new ViewHolder();
        holder.titr = (TextView) vi.findViewById(R.id.listtext);
        holder.image = (ImageView) vi.findViewById(R.id.listimg);
        holder.image.setTag(position);
        vi.setTag(holder);
    }
    else{
        holder = (ViewHolder) vi.getTag();
    }


    holder.titr.setText(items.get(position));
if(sp.getBoolean("position="+position, false)){
    v.setBackgroundResource(R.drawable.fav_ic);
}
    holder.image.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
           v.setBackgroundResource(R.drawable.fav_ic);

SharedPreferences.Editor edit = sp.edit();
edit.putBoolean("position="+position, true);
edit.commit();

        }
    });
    return vi;
}
Ameer Faisal
  • 355
  • 1
  • 9
2

try this,

public class CustomBaseAdapter extends BaseAdapter {

Context context;
ArrayList<Items> items;

     public CustomBaseAdapter(Context context,ArrayList<Items> items){
        this.context = context;
        this.items = items;
    }

    private class ViewHolder{
    TextView titr;
    ImageView image;
    }

@Override
public int getCount() {
    return items.size();
}

@Override
public Items getItem(int position) {
    return items.get(position);
}

@Override
public long getItemId(int position) {
    return items.hashCode();
}

@Override
public View getView(int position, View view, ViewGroup parent) {
    View vi = view;
    final ViewHolder holder ;

    LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    if(view==null){

        vi = inflater.inflate(R.layout.customlistitem,null);
        holder = new ViewHolder();
        holder.titr = (TextView) vi.findViewById(R.id.listtext);
        holder.image = (ImageView) vi.findViewById(R.id.listimg);
        holder.image.setTag(position);
        vi.setTag(holder);
    }
    else{
        holder = (ViewHolder) vi.getTag();
    }


    holder.titr.setText(items.get(position).getStrTxt());
    holder.image.setImageResource(items.get(position).getDrawableImage());
    holder.image.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            items.set(position,new Items(R.drawable.fav_ic));
            notifyDataSetChanged();
        }
    });
    return vi;
}
}

Add Model Class :

public class Items {


    int drawableImage;
    String strTxt;


  public Items(int drawableImage) {
    this.drawableImage = drawableImage;
   }
    public int getDrawableImage() {
        return drawableImage;
    }

    public void setDrawableImage(int drawableImage) {
        this.drawableImage = drawableImage;
    }

    public String getStrTxt() {
        return strTxt;
    }

    public void setStrTxt(String strTxt) {
        this.strTxt = strTxt;
    }
}
Pradeep Gupta
  • 1,770
  • 1
  • 9
  • 23
1

You should define layoutInflater in the constructor because getView() call for each row so if you define layoutInflater in getView() then LayoutInflater define again and again for each row.

PRIYA PARASHAR
  • 777
  • 4
  • 15
1

Yes, this problem appears always in ListView because android always destroy and recreate rows in it.

You have two choices:

First, Modify your Adapter to save status for each row in the ListView and check this status before displaying the row.

Second one, I recommended this one and use it in my code, you can use RecyclerView, this problem will not happen with it.

Ahmed M. Abed
  • 599
  • 3
  • 9
  • 22