listview recycling strange empty space
Asked Answered
M

2

2

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.

Madlynmadman answered 18/6, 2012 at 21:28 Comment(4)
Just to clarify: You have rows in a list which contain (one or more) dynamically-sourced images. The list items will grow automatically to fit the largest (tallest) image, but when you scroll the list and it recycles the views the views will not shrink if the largest image is shorter than the list row?Ever
@Ever yes. indeed you explained it better :)Anile
Does the row determine how to grow to fit the images programatically or in XML?Ever
@Ever I have edited my question. I am not doing anything specific to determine the row height. It is dynamically determined.Anile
E
2

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.

Ever answered 18/6, 2012 at 22:22 Comment(3)
Without recycling the list is useless because it is too much slow. I can't make the all images at the same height. Even I do that, I will have the same problem since the number of images in a row is not fixed.Anile
Hmm. Can you post the full xml for the listview row? (specifically, the part where the images go...)Ever
there is no xml for images. images are added to textview asynchronously. I am using html imagegetter as here: #2865952Anile
B
1

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

Birdhouse answered 29/9, 2014 at 8:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.