When I first needed to set a message on a ListView that was empty, I tried different methods, but none of them worked, except the one that I will describe in this tutorial. So let’s start.
When you want to show a message to the user when the ListView is empty, you have to keep in mind the following 3 steps:
- In the xml where the ListView is declared, create a TextView (the TextView can be inside a LinearLayout if you want) right below the ListView
- Set the TextView’s id as “emptyElement”
- And inside the activity, set the setEmptyView() property to the ListView
1.  Create an xml which will hold the ListView and name it “my_activity” and an activity called “MyActivity”.
2. Now, in the just created xml “my_activity”, you will have to set the ListView.  And right below the ListView, you will have to add a TextView. This will be used to display the empty message.
Important: The TextView must have as id the following name: “emptyElement”. This name is mandatory. The message won’t be displayed if you use another name.
This is how “my_activity” xml should look like:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MyActivity">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/listView"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/emptyElement"
android:text="The list is empty"
android:textStyle="bold"
android:textSize="15sp"
android:visibility="gone"
android:layout_centerInParent="true"
android:textColor="@android:color/darker_gray"/>
</RelativeLayout>
3. Create an xml for displaying items (when the list is not empty), and name it “list_item”.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/list_item"
android:gravity="center_vertical">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/list_item_text_view"
android:textSize="20sp"
android:padding="10dp"
android:layout_marginLeft="5dp"/>
</LinearLayout>
4. Create a new Java class for the custom adapter which will be used by the ListView and name “MyCustomAdapter”. The code for the adapter is written below:
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import java.util.ArrayList;
public class MyCustomAdapter extends BaseAdapter {
private ArrayList<String> mListItems;
private LayoutInflater mLayoutInflater;
public MyCustomAdapter(Context context, ArrayList<String> arrayList){
mListItems = arrayList;
//get the layout inflater
mLayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
//getCount() represents how many items are in the list
return mListItems.size();
}
@Override
//get the data of an item from a specific position
//i represents the position of the item in the list
public Object getItem(int i) {
return null;
}
@Override
//get the position id of the item from the list
public long getItemId(int i) {
return 0;
}
@Override
public View getView(int position, View view, ViewGroup viewGroup) {
// create a ViewHolder reference
ViewHolder holder;
//check to see if the reused view is null or not, if is not null then reuse it
if (view == null) {
holder = new ViewHolder();
view = mLayoutInflater.inflate(R.layout.list_item, null);
holder.itemName = (TextView) view.findViewById(R.id.list_item_text_view);
// the setTag is used to store the data within this view
view.setTag(holder);
} else {
// the getTag returns the viewHolder object set as a tag to the view
holder = (ViewHolder)view.getTag();
}
//get the string item from the position "position" from array list to put it on the TextView
String stringItem = mListItems.get(position);
if (stringItem != null) {
if (holder.itemName != null) {
//set the item name on the TextView
holder.itemName.setText(stringItem);
}
}
//this method must return the view corresponding to the data at the specified position.
return view;
}
/**
* Static class used to avoid the calling of "findViewById" every time the getView() method is called,
* because this can impact to your application performance when your list is too big. The class is static so it
* cache all the things inside once it's created.
*/
private static class ViewHolder {
protected TextView itemName;
}
}
5. Now go to MyActivity class and add the code below:
import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;
import java.util.ArrayList;
import java.util.List;
public class MyActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_activity);
ListView listView = (ListView) findViewById(R.id.listView);
// Create an empty array list of strings
List<String> items = new ArrayList<String>();
// Set the adapter
MyCustomAdapter adapter = new MyCustomAdapter(items);
listView.setAdapter(adapter);
// Set the emptyView to the ListView
listView.setEmptyView(findViewById(R.id.emptyElement));
}
}
And this is it. Now, if you run the app you should see something like this:
And if you populate the ArrayList of Strings, the message will disappear and the list items will be displayed.  (You can use a for statement in MyActivity where the empty array was created in order to populate the array of strings)
for (int i = 0; i < 5; i++) {
items.add("Item " + i);
}


