Search code examples
androidlistviewsimpleadapter

Calling view by id in customized SimpleAdapter?


I want to add some customized operations when use a SimpleAdapter for a ListView. So I write a MySimpleAdapter to extend SimpleAdapter. I need to hide an ImageView if the image url is null. However, when view recycling works, those views with visible ImageView are also hidden when scrolling up and down.

The codes are as below:

public class MySimpleAdapter extends SimpleAdapter {
  ...
  public View getView(int position, View convertView, ViewGroup parent) {
    View vi = convertView;        
    vi=super.getView(position, convertView, parent);//other parts rather than the ImageView will behave normally

    @SuppressWarnings("unchecked")
    HashMap<String, Object> data = (HashMap<String, Object>) getItem(position);

    //below is the problematic part
    if(data.get("url")!=null){
        setImageWithUrl(data.get("url").toString(), (ImageView) vi.findViewById(R.id.my_image));//setImageWithUrl is a function containing my extra operations
    }else{
        ((ImageView) vi.findViewById(R.id.my_image)).setVisibility(View.GONE);//hide the image as it has a border but no content
    }

    //in contrast, setting image drawable is always right
    if(data.get("url2")!=null){
        setImageWithUrl(data.get("url2").toString(), (ImageView) vi.findViewById(R.id.my_image_2));
    }else{
      ((ImageView)vi.findViewById(R.id.my_image_2)).setImageDrawable(mContext.getResources().getDrawable(R.drawable.default_image));
    }
  }
}

The problem is like (say the screen shows 3 rows of the ListView:

[1=====] <a row with visible image
[2=====] <a row with visible image
[3=====] <a row with visible image
--------- below is out of screen
[4=====] <a row with hidden image

Scroll down to the 4th row so the 1th is out of screen. Then scroll back to 1th and 4th is out of screen. then 1th is a row with hidden image @id/my_image. I think this is due to "findViewById". But why setting the image with drawable resources is always right (for @id/my_image_2)?

I am not quite familiar the the details of the inflater and recycling mechanism. How can I avoid this within this codes? Or do I need to use other adapters?

PS,

The row xml structure is simple, something like:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">
    <TextView
        android:id="@+id/title_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <ImageView
        android:id="@+id/my_image"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="@layout/border_style" />
    <ImageView
        android:id="@+id/my_image_2"
        android:layout_width="100dp"
        android:layout_height="100dp" />
    ...
</LinearLayout>

Solution

  • ListView reuses views so you need to implement hide/restore logic. Add set visibility to visible in the code.

     //below is the problematic part
        if(data.get("url")!=null){
      ((ImageView) vi.findViewById(R.id.my_image)).setVisibility(View.VISIBLE);
            setImageWithUrl(data.get("url").toString(), (ImageView) vi.findViewById(R.id.my_image));//setImageWithUrl is a function containing my extra operations
        }else{
            ((ImageView) vi.findViewById(R.id.my_image)).setVisibility(View.GONE);//hide the image as it has a border but no content
        }