0

I'm having a problem while implementing a "mark as favorite" function in my listview. I have an ImageButton placed on the right side of every listview item and "on click" I want to change the image of the button. It should look like this:

enter image description here

That's pretty easy to implement and works perfectly fine. The problem now is when I scroll the list, the selected image buttons (stars) won't stay the same.

To keep the selection of a listview item isn't that hard, but to keep the changed image in the list is an issue for me. The former can be implemented in this way: https://stackoverflow.com/a/9281155/2054118

So I tried something similar. In the getView() method I init my imagebutton and its OnClickListener to save the actual position in a LinkedList. All positions of the selected ImageButtons should be in the list:

MyAdapter.java:

private LinkedList<Integer> selectedIndeces;

...

private static class ViewHolder {
    ...
    public ImageButton favoriteButton;
}

public void changeSelectedPositions(int pos) {
    int index = this.selectedIndeces.indexOf(pos);
    if (index != -1) {
        // image button in this row was selected
        this.selectedIndeces.remove(index);
    } else {
        // mark position of the image button as selected
        this.selectedIndeces.add(pos);
    }
    notifyDataSetChanged();
}

...

@Override
public View getView(final int position, View convertView, ViewGroup parent) {

    View rowView = convertView;

    // reuse views
    if (rowView == null) {
        rowView = this.mInflater.inflate(R.layout.talk_list_child, null);
        // configure view holder
        ViewHolder viewHolder = new ViewHolder();

        ...

        ImageButton ib = (ImageButton) rowView.findViewById(R.id.ib_favorite);
        ib.setFocusable(false);
        ib.setFocusableInTouchMode(false);
        ib.setOnClickListener(new OnClickListener() {
            public void onClick(View button) {
                // Set the button's appearance
                button.setSelected(!button.isSelected());
                changeSelectedPositions(position);
            }
        });
        viewHolder.favoriteButton = ib;
    }

    // fill data
    ViewHolder holder = (ViewHolder) rowView.getTag();

    ...

    if (selectedIndeces.contains(position)) {
        holder.favoriteButton.setImageResource(R.drawable.fav_selected);
    } else {
        holder.favoriteButton.setImageResource(R.drawable.fav_unselected);
    }

}

But the problem is that the position I get in getView() isn't always the same and depends on where the list is scrolled to?

So to shorten my question: How can I keep the selection/image of my ImageButtons in the ListView even when I scroll?

Community
  • 1
  • 1
Trat0rn
  • 53
  • 9
  • Look at the [ViewHolder](http://developer.android.com/training/improving-layouts/smooth-scrolling.html#ViewHolder) pattern. :) – Eran Goldin Aug 17 '14 at 11:25
  • @EranGoldin Thanks, but I used the ViewHolder pattern. I probably cut too much off my code, because I wanted to keep it clear, but I edited my post now so you can see that I used the pattern. – Trat0rn Aug 17 '14 at 11:40

2 Answers2

1

You saved your position while preparing viewHolder. Then after scrolling, view is recycled and the same viewHolder with previously stored position is used. You can just set listener every time you get getView() call.

Move

ib.setOnClickListener(new OnClickListener() {
    public void onClick(View button) {
        // Set the button's appearance
        button.setSelected(!button.isSelected());
        changeSelectedPositions(position);
    }
});

Just before

if (selectedIndeces.contains(position)) {
asylume
  • 534
  • 3
  • 6
  • Thanks for the answer, worked great. :) Now when I think about it, it's pretty obvious, but I couldn't find my error... – Trat0rn Aug 17 '14 at 11:44
1
  1. Keep an array list to save the position which is clicked in your adapter

    iconClickedPostion = new ArrayList();

  2. Whenever you handle your click for the image button in the list, add the position of the listview in the arraylist.

    iconClickedPostion.add(position);

  3. In getView(), check the condition if it is already clicked then set the desired image.

    if(iconClickedPostion.contains(position)){ completedIcon.setImageResource(R.drawable.ic_done); } else { completedIcon.setImageResource(iconId[position]); }

Trideep Rath
  • 3,623
  • 1
  • 25
  • 14