[android] Showing empty view when ListView is empty

For some reason the empty view, a TextView in this case, always appears even when the ListView is not empty. I thought the ListView would automatically detect when to show the empty view.

<RelativeLayout android:id="@+id/LinearLayoutAR"
    android:layout_height="fill_parent"
    android:layout_width="fill_parent">
    <ListView android:id="@+id/ARListView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"></ListView>
    <ProgressBar android:id="@+id/arProgressBar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"></ProgressBar>
    <!-- Here is the view to show if the list is emtpy -->
    <TextView android:id="@id/android:empty"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="No Results" />
</RelativeLayout>

How can I hook up the empty view properly?

This question is related to android listview

The answer is


I highly recommend you to use ViewStubs like this

<FrameLayout
    android:layout_width="fill_parent"
    android:layout_height="0dp"
    android:layout_weight="1" >

    <ListView
        android:id="@android:id/list"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />

    <ViewStub
        android:id="@android:id/empty"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout="@layout/empty" />
</FrameLayout>

See the full example from Cyril Mottier


As appsthatmatter says, in the layout something like:

<ListView android:id="@+id/listView" ... />
<TextView android:id="@+id/emptyElement" ... />

and in the linked Activity:

this.listView = (ListView) findViewById(R.id.listView);
this.listView.setEmptyView(findViewById(R.id.emptyElement));

Does also work with a GridView...


<ListView android:id="@+id/listView" ... />
<TextView android:id="@+id/empty" ... />
and in the linked Activity:

this.listView = (ListView) findViewById(R.id.listView);
this.listView.setEmptyView(findViewById(R.id.empty));

This works clearly with FragmentActivity if you are using the support library. Tested this by building for API 17 i.e. 4.2.2 image.


Just to add that you don't really need to create new IDs, something like the following will work.

In the layout:

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

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@android:id/empty"
    android:text="Empty"/>

Then in the activity:

    ListView listView = (ListView) findViewById(android.R.id.list);
    listView.setEmptyView(findViewById(android.R.id.empty));

I tried all the above solutions.I came up solving the issue.Here I am posting the full solution.

The xml file:

<RelativeLayout
    android:id="@+id/header_main_page_clist1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="20dp"
    android:paddingBottom="10dp"
    android:background="#ffffff" >

    <ListView
        android:id="@+id/lv_msglist"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:divider="@color/divider_color"
        android:dividerHeight="1dp" />

    <TextView
        android:id="@+id/emptyElement"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="NO MESSAGES AVAILABLE!"
        android:textColor="#525252"
        android:textSize="19.0sp"
        android:visibility="gone" />
</RelativeLayout>

The textView ("@+id/emptyElement") is the placeholder for the empty listview.

Here is the code for java page:

lvmessage=(ListView)findViewById(R.id.lv_msglist);
lvmessage.setAdapter(adapter);
lvmessage.setEmptyView(findViewById(R.id.emptyElement));

Remember to place the emptyView after binding the adapter to listview.Mine was not working for first time and after I moved the setEmptyView after the setAdapter it is now working.

Output:

enter image description here


A programmatically solution will be:

TextView textView = new TextView(context);
textView.setId(android.R.id.empty);
textView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
textView.setText("No result found");
listView.setEmptyView(textView);

Activity code, its important to extend ListActivity.

package com.example.mylistactivity;

import android.app.ListActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import com.example.mylistactivity.R;

// It's important to extend ListActivity rather than Activity
public class MyListActivity extends ListActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.mylist);

        // shows list view
        String[] values = new String[] { "foo", "bar" };

        // shows empty view
        values = new String[] { };

        setListAdapter(new ArrayAdapter<String>(
                this,
                android.R.layout.simple_list_item_1,
                android.R.id.text1,
                values));
    }
}

Layout xml, the id in both views are important.

<?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">

    <!-- the android:id is important -->
    <ListView
        android:id="@android:id/list"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"/>

    <!-- the android:id is important -->
    <TextView
        android:id="@android:id/empty"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:text="i am empty"/>
</LinearLayout>

First check the list contains some values:

if (list.isEmpty()) {
    listview.setVisibility(View.GONE);
}

If it is then OK, otherwise use:

else {
     listview.setVisibility(View.VISIBLE);
}

I had this problem. I had to make my class extend ListActivity rather than Activity, and rename my list in the XML to android:id="@android:id/list"


When you extend FragmentActivity or Activity and not ListActivity, you'll want to take a look at:

ListView.setEmptyView()