Search code examples
androidandroid-arrayadapterandroid-listfragment

ListFragment with custom layout: empty message always displayed


I have created a custom layout for ListFragment, using the default ArrayAdapter. My problem is that the empty message is displayed on each row, when the list is not empty (when the list is empty, the message is displayed only once as expected).

headline_list.xml (i.e. my custom layout file)

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ListView
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:id="@id/android:list" />

    <TextView android:id="@+id/my_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <TextView android:id="@id/android:empty"
        android:text="There are no data"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/> 

</LinearLayout>

HeadlineFragment.java

public class HeadlineFragment extends ListFragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
        return inflater.inflate(R.layout.headline_list, container, false);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        List<String> headlines = ...;          // populate headlines list

        setListAdapter(new ArrayAdapter<String>(getActivity(),
                R.layout.headline_list, R.id.my_text, headlines));
    }
}

enter image description here


Solution

  • You've got your layouts a little mixed up.

    new ArrayAdapter<String>(getActivity(),
        R.layout.headline_list, R.id.my_text, headlines)
    

    The second parameter in the ArrayAdapter constructor is meant to be the ID for an individual row's layout, not the entire Fragment layout. The third parameter references a TextView within the row layout to display the item's data.

    You can provide your own row layout, or you can use one provided by the SDK. An example of the latter:

    new ArrayAdapter<String>(getActivity(),
        android.R.layout.simple_list_item_1, headlines)
    

    In this example, android.R.layout.simple_list_item_1 is itself just a TextView, so we don't need to provide the ID for one.

    Also, you should consider keeping a reference to the Adapter, should you need to later modify it.


    It appears that you mean for the my_text TextView to be your custom row layout. If so, remove it from the Fragment's layout, headline_list, and put it in its own layout file; e.g., list_row.xml. Your layout files would then be as follows:

    headline_list.xml

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    
        <ListView android:id="@id/android:list"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    
        <TextView android:id="@id/android:empty"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="There are no data" /> 
    
    </LinearLayout>
    

    list_row.xml

    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/my_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    

    Then you would instantiate your Adapter like so:

    new ArrayAdapter<String>(getActivity(), R.layout.list_row, headlines)
    

    Again, since the row layout is just a TextView, we don't need to pass an ID in the constructor for one.