Nikolaj
Nikolaj

Reputation: 145

Android: changing ImageView in one ListView item changes the same ImageView in other ListView items?

My ListView item consists of the following components - TextView and then under it there is one ImageView - like.

So when I click on like I want to be able to change the like ImageView from grey to blue.

At the moment when I click on like the like ImageView does change from grey to blue. But not only for the corresponding ListView item but for every 3rd item in the list - so if I have 10 items in my list and I click on the like of the first item in the list then 4th, 7th and 10th items like ImageView change from grey to blue.

In my post_list_item.xml in the root element of the file I specified the following android:descendantFocusability="blocksDescendants" but it doesn't help either.

My question is - what do I have to do so that when I click on like I would be able to change the like ImageView from grey to blue without affecting other list items?

Here is my code:

public class CustomListAdapter extends BaseAdapter {

    LayoutInflater inflater;
    ArrayList<Post> list;
    public CustomListAdapter(PostActivity postActivity, ArrayList<Post> list) {
        inflater = LayoutInflater.from(postActivity);
        this.list = list;
    }
    @Override
    public int getCount() {
        return list.size();
    }

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

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

    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            convertView = inflater.inflate(R.layout.post_list_item, parent, false);
            holder = new ViewHolder();
            holder.tvPost = (TextView) convertView.findViewById(R.id.tvPost);
            holder.ivLike = (ImageView) convertView.findViewById(R.id.ivLike);
            holder.tvLikes = (TextView) convertView.findViewById(R.id.tvLikeCount);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        Post post = list.get(position);
        holder.tvPost.setText(post.getPost());
        holder.tvLikes.setText(post.getLiked());
        holder.ivLike.setOnClickListener(mClickListener);
        holder.ivLike.setTag(position);
        return convertView;
    }
    private View.OnClickListener mClickListener = new View.OnClickListener() {

        public void onClick(View v) {
            int pos = (Integer) v.getTag();
            Post post = (Post) list.get(pos);
            post.setIvLike(v);
            CustomListAdapter.this.notifyDataSetChanged();

        }

    };
    static class ViewHolder
    {

        TextView tvPost ;
        TextView tvLikes;
        ImageView ivLike;

    }
}

Post.java

public class Post {

    String post;
    String liked;


    public void setIvLike(View view){
        if(view.isActivated())
            view.setActivated(false);
        else
            view.setActivated(true);
    }


    public String getPost() {
        return post;
    }

    public void setPost(String post) {
        this.post= post;
    }


    public String getLiked() {
        return liked;
    }

    public void setLiked(String liked) {
        this.liked = liked;
    }
}

Upvotes: 1

Views: 317

Answers (2)

Fahad Rehman
Fahad Rehman

Reputation: 1199

You need to have a property in your Post Class to track that post has been liked

Updated Post.Java

public class Post {

String post;
String liked;
public bool isLiked;  // Add this


public void setIvLike(View view){
    if(!isLiked)
        view.setActivated(false);
    else
        view.setActivated(true);
}


public String getPost() {
    return post;
}

public void setPost(String post) {
    this.post= post;
}


public String getLiked() {
    return liked;
}

public void setLiked(String liked) {
    this.liked = liked;
}

}

And in getView method of Adapter

public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder;
    if (convertView == null) {
        convertView = inflater.inflate(R.layout.post_list_item, parent, false);
        holder = new ViewHolder();
        holder.tvPost = (TextView) convertView.findViewById(R.id.tvPost);
        holder.ivLike = (ImageView) convertView.findViewById(R.id.ivLike);
        holder.tvLikes = (TextView) convertView.findViewById(R.id.tvLikeCount);
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }
    Post post = list.get(position);
    holder.tvPost.setText(post.getPost());
    holder.tvLikes.setText(post.getLiked());
    holder.ivLike.setOnClickListener(mClickListener);
    holder.ivLike.setTag(position);
    holder.setIvLike(ivLike);  //  Add this 
    return convertView;
}
private View.OnClickListener mClickListener = new View.OnClickListener() {

    public void onClick(View v) {
        int pos = (Integer) v.getTag();
        list.get(pos).isLiked = true;

       // post.setIvLike(v);  // No need to update here
        CustomListAdapter.this.notifyDataSetChanged();

    }

};

Upvotes: 1

Andrew G
Andrew G

Reputation: 2614

  1. You're not "resetting" the view in getView when a view is reused. You need to set the recycled view back to the correct state. This is done after the if-else block where you create or reuse a ViewHolder.

  2. setIvLike will need to modify that Post object in one way or another such that when it is scrolled off screen the view can be recreated exactly as it appeared even if it is using a recycled view. For that reason it is important to know which properties of the view you change and consistently set every one of those properties in getView after reuse/creation.

Upvotes: 2

Related Questions