Question

I have a similar problem to the one in this question: ListView and rows recycling problem

Above is solved. but same solution does not work for me.

I have a listview consisting of textviews. Each textview can contain variable number of images. I am getting images with html.imagegetter and I am using recycling in getview method of list adapter.

If there is one or more images in a textview, it will have a height to be able to fit its content. When this textview is recycled and new content does not fill the height defined before, then empty space will appear.

The problem is that I can't restore the textview height in getview because I dont know what height the next list item will have.

this is my getview:

public View getView(int position, View convertView, ViewGroup parent) {
    final ViewHolder holder;

    View rowView = convertView;
    if (rowView == null) {
        LayoutInflater inflater = context.getLayoutInflater();
        rowView = inflater.inflate(resource, parent, false);
        holder = new ViewHolder();
        holder.imgAvatar = (ImageView) rowView.findViewById(R.id.imgAvatar);
        holder.textDetails = (TextView) rowView.findViewById(R.id.textDetails);
        holder.textPostTime = (TextView) rowView.findViewById(R.id.textPostTime);
        holder.textPost = (TextView) rowView.findViewById(R.id.textPost);
        rowView.setTag(holder);
    } else {
        holder = (ViewHolder) rowView.getTag();
    }

    holder.textDetails.setText(details.toString());
    holder.textPostTime.setText(x.postTime);
    holder.textPost.setText(Html.fromHtml(x.postBody, new URLImageGetter(holder.textPost, context), null, context));
    return rowView;
}

this is row layout:

<TextView
    android:ellipsize="none"
    android:autoLink="web"
    android:textColor="#000000"
    android:id="@+id/textPost"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

THE PROBLEM: The listview recycling mechanism can't calculate the new height for used views according to its new contents. Without recycling, it is too slow.

Was it helpful?

Solution

So, essentially your problem is with recycling the views. When your views get inflated from XML they look at the images and decide how tall to be. This works fine because the inflater can cause the height to be "wrap_content" aka however tall the tallest child component is - this is dynamic.

However, when your getview recycles the old views it (for some reason) isn't updating the height of the rows, and neither are you (which you never had to do before because the inflater handles it automatically from "wrap_content"). It would appear from what you described that you just get a row with whatever the height of the view happened to be set at previously (this previous value was set by the inflater automatically).

Your two solutions are:

  1. Don't recycle the views - just inflate a new one every time. You will see a performance hit which will probably only be noticeable at lists with ~50 elements or more. If it is a small list this may be the easiest (code-wise) option, although there it will still operate slightly slower.
  2. Keep recycling the views - if you pick this you will have to set the height of the row (or text view, whatever is determining it) yourself based on the image heights. This is doable but will require more work. I'd suggest
  3. secret option 3 - normalize the image heights - If you would a.) like to continue recycling views but b.) don't want to write the code to set the row heights manually and c.) resizing the images wouldn't kill your app, you could use the setMaxHeight(int) method to make sure all of your images are the same height (or use a method like this to resize the images to a predetermined size)

Note: I am pretty sure (almost certain) that, normally, if height is set to "wrap_content" it would wrap to the new content size (since it normally updates the size when the content is updated). I couldn't say why this is not happening for you - it may be that something inside the "wrap_content" has its size set to a concrete value and thus isn't resizing, so the "wrap_content" isn't changing even though there is empty space.

OTHER TIPS

Try using requestLayout on your image and textviews. It will help the listview recompute the height of recycled views.

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