Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ListView of WebViews - reusing items of different height fails; asks for all views before displaying any

I have an activity that displays a ListView. Each item in the ListView is a LinearLayout consisting of one WebView. There are potentially hundreds of items in the list and each is a different height.

First problem is that when reusing a recycled view in getView(), the new view is always the height of the original view, even though I've set the layout_height for both the LinearLayout and the WebView to wrap_content.

Second problem is that getView() seems to be getting called for every item in the list even though only the first five or six fit on the screen. I haven't seen this when using other list item types. For example, in another place I a list of custom views that are all the same height and I only see getView() being called for the number of views that initially fit on the screen.

So... I need to figure out how to force recycled WebViews to render their new contents so their height can be calculated instead of just using the previous height. And I'd like to know why the system is asking me for ALL my items in this case.

Here's the requisite code snippets:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <ListView 
        android:id="@+id/topPane"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:dividerHeight="1.0px"
        android:divider="#FFFFFF"
        android:smoothScrollbar="false"
        />
</LinearLayout>

Rows are built from:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    >
    <WebView 
        android:id="@+id/rowWebView"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:padding="0.0px"
        android:scrollbars="none"
        />
</LinearLayout>

This is getView() in my adapter. HTML snippets come from an array of Strings for now.

    @Override
    public View getView(int position, View convertView, ViewGroup parent)
        {
        String item = (String) getItem(position);
        if (convertView == null)
            {
            convertView = (LinearLayout) LayoutInflater.from(context).inflate(R.layout.rowview, parent, false);
            }
        WebView wv = (WebView) convertView.findViewById(R.id.rowWebView);
        wv.loadDataWithBaseURL(null, item, "text/html", "utf-8", "about:blank");
        return convertView;
        }
like image 307
Craig Avatar asked Jan 27 '11 17:01

Craig


People also ask

What is a ListView?

Android ListView is a ViewGroup that is used to display the list of items in multiple rows and contains an adapter that automatically inserts the items into the list. The main purpose of the adapter is to fetch data from an array or database and insert each item that placed into the list for the desired result.

What is ListView how do you use it in Android application explain with example?

Android ListView is a view which groups several items and display them in vertical scrollable list. The list items are automatically inserted to the list using an Adapter that pulls content from a source such as an array or database.

Is ListView deprecated Android?

ListView Class (Android. Widget) | Microsoft Learn. This browser is no longer supported.


1 Answers

I think the problem is that with the code you wrote the system is measuring first the container height (row linear_layout), and later the content (WebView). But second measure doesn't affect the first one until you call invalidate or some method that makes the container to recalculate his size.

About why your getView method is called many times check your getViewTypeCount() method of your adapter.

 @Override
 public int getViewTypeCount()
 {
     return NumberOfTypeOfViewsInYourList;
 }

Documentation states that:

"this method returns the number of types of Views that will be created by getView(int, View, ViewGroup). Each type represents a set of views that can be converted in getView(int, View, ViewGroup). If the adapter always returns the same type of View for all items, this method should return 1. This method will only be called when when the adapter is set on the the AdapterView."

I had a problem with this method, giving a big number (like 5000) made my app crash, it looks like it's used internally for some ListView calculations.

Hope it helps somehow.

BTW, there is a very good talk about the world of ListViews

like image 121
Axel M. Garcia Avatar answered Nov 09 '22 15:11

Axel M. Garcia