Question

I have a ListView where each item contains a pretty large picture and some text. It is basically like a feed in other familiar apps.

In my ListView I have in total 4 items. However, only 2 of them are visible at the same time. I have set an OnClickListener on each item that flips the item around and shows some new info.

When I click the first item, it is flipped, but when I scroll down, the fourth item is also flipped. In other words, item #1 and #4 is reacting on the same behavior.

If I shrink each item such that the whole ListView is visible on the screen, only the clicked item is flipped. This is the behavior I want. I suspect this has something to do with the fact that the getView() of the adapter method is allowed to reuse the associated view via the convertView parameter. But I haven't been able to figure out how to solve this.

Any ideas how I can achieve the behavior I want?

EDIT: getView()-method

 public View getView(int position, View convertView, ViewGroup parent) {
            View v = convertView;
            if (v == null) {
                LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                v = vi.inflate(R.layout.row_list_view, null);
            }
            final Item item = items.get(position);
            if (item != null) {
                    TextView listPos = (TextView) v.findViewById(R.id.listPosText);
                    TextView caption = (TextView) v.findViewById(R.id.contactInfoText); 
                    if(ad.getPosition()!=null)
                        listPos.setText(item.getPosition());
                    if(ad.getCaption()!=null)
                        caption.setText(item.getCaption());
                    final ViewFlipper cardFlipper = v.findViewById(R.id.flipper);
                    RelativeLayout front = (RelativeLayout) v.findViewById(R.id.listImageFront);
                    front.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                         AnimationFactory.flipTransition(cardFlipper, FlipDirection.RIGHT_LEFT);
                    }
                    });
                    RelativeLayout back = (RelativeLayout) v.findViewById(R.id.listImageBack);
                    back.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                         AnimationFactory.flipTransition(cardFlipper, FlipDirection.RIGHT_LEFT);
                    }
                });
                    com.list.components.AspectRatioImageView imgView = (com.list.components.AspectRatioImageView) v.findViewById(R.id.listMainImage);
                    String imageid = "";
                    try {
                        imageid = item.getImages().getString(0);
                    } catch (JSONException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    imageLoader.DisplayImage("myURL"+imageid, imgView, back);
            }
            return v;
    }
Was it helpful?

Solution

You will need to a boolean flag for each list item (so in the Object class that supplies the ArrayAdapter) to alert which ones are flipped or not. It is exactly because of views being recycled.

// in your `Object` class that supplies the `ArrayAdapter`
boolean isFlipped = false;

// in the ArrayAdapter
Object.setOnClickListener(new OnClickListener() {
    Object.setIsFlipped(true);
});

// in getView() method
if (arrayOfObjects.get(position).getIsFlipped()) {
   // show flipped info
}
else {
   // unshow flipped info
}

OTHER TIPS

In getView you will get the convertView as an argument. The convertView is the view that will be reused. With this knowledge it should be fairly easy to check if the view is flipped and, if so, flip it back.

When you shrink the items down it will have to make extra views since it will only reuse the views that are not visible on the screen. You will notice however, if you add more items, the same flipping "problems" as with small items will occur.

I'm assuming you are setting the listener in the getView() method? I had a similar problem with toggle buttons in children for an expandable list view. I solved this by storing the view (buttons in my case) in a sparse array, and only setting the listeners once, when the value was null for that key.

private SparseArray<ToggleButton> buttons1;
private SparseArray<ToggleButton> buttons2;

...

@Override
public View getChildView(int groupPosition, int childPosition,
        boolean isLastChild, View view, ViewGroup parent)
{
...
    if(buttons1.get(groupPosition, null) == null)
    {       
        //add favoriteButton to array at group position
        buttons2.put(groupPosition, b2);
        buttons1.put(groupPosition, b1);

        b2.setOnClickListener( new OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
               //...
            }
        });

        b1.setOnClickListener( new OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                   //...
            }
        });
    }
    //add buttons to array at group position
    buttons2.put(groupPosition, b2);
    buttons1.put(groupPosition, b1);
    return view;
}

b1 and b2 are toggle buttons found by id earlier in the code.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top