Android displaying text when ListView is empty
Asked Answered
W

7

35

I'm setting a TextView with the id @android:id/empty to display a message when there are no items in the ListView. However, this TextView gets displayed even if there are items in the ListView, right before the items show up.

How can I make it such that it only gets displayed when there are no elements in the ListView?

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

<ListView
    android:id="@android:id/list"
    android:layout_width="wrap_content"
    android:layout_height="fill_parent"
    android:dividerHeight="1dp" >
</ListView>

<TextView 
    android:id="@android:id/empty"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/empty_list" />

</LinearLayout>

PS: I'm using a Loader and a SimpleCursorAdapter with a ListFragment.

Willyt answered 4/4, 2012 at 18:24 Comment(1)
Just set the textview visibility gone initially!! If listview has some data, set visibility visible and set some text programaticallyBravery
G
106

I'm guessing you are using a regular Fragment or Activity with a ListView inside of it. If you are, you must add the empty layout to the ListView manually.

E.g.

ListView lv = (ListView)findViewById(android.R.id.list);
TextView emptyText = (TextView)findViewById(android.R.id.empty);
lv.setEmptyView(emptyText);

Then your ListView will automatically use this view when its adapter is empty

If you are using a ListActivity you do not need to call setEmptyView() on the ListView since the ListActivity automatically manages that for you.

Gyrostabilizer answered 4/4, 2012 at 18:39 Comment(7)
I tried the code you posted and now it works. I'm using a ListFragment, do you know why I needed to add the extra code ? Thanks.Willyt
Yes, in a ListFragment instead of using an empty view you should call setEmptyText("empty listview"); I don't believe a ListFragment supports setting an empty view automatically.Gyrostabilizer
When I add it, i gets this exception "java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first." Any clue what I am doing wrong?Kalina
@Kalina - It's hard to tell without seeing your code / xml files. You might want to google the problem and if you can't find a solution post a new question on stackoverflowGyrostabilizer
In my case the ListFragment added the Empty View by itself in API 16+, but in API14 it didn't, so i had to do it by myself in this way :-/Telemotor
Thanks, it worked but has a bad side effect, the empty TextView is visible all the time, isn't it suppose to be hidden automatically by ListView control when it populates items, and gets visible once it has no more items? I'm using it in a ListView with a custom ArrayAdapter. I'm using API 16+Bud
@Astrount, it's enough to set android:visibility="gone" attribute in a <TextView> tag.Wessling
S
11

Set a TextView and assign to it whatever you want to display when the ListView is empty:

ProjectListAdapter projectListAdapter = new ProjectListAdapter();
TextView empty=(TextView)findViewById(R.id.empty);
projectsListView.setEmptyView(empty);

And in my xml file we write the below code

<TextView
      android:id="@+id/empty"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:layout_gravity="center"
      android:gravity="center"
      android:text="Your text here"
      android:textColor="#FFFFFF" />
Shagbark answered 5/12, 2013 at 10:34 Comment(0)
B
5

I had this problem. You have to set the emptyView explicitly in your code.

Change your TextView:

<TextView 
    android:id="@+id/emptyResults"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/empty_list" />

Then in the onCreate():

listViewResults = (ListView) findViewById(R.id.list);
listViewResults.setEmptyView((LinearLayout) findViewById(R.id.emptyResults)); 

This code above assumes your ListView is in a LinearLayout.

Byrdie answered 4/4, 2012 at 18:43 Comment(0)
F
4

I used ListFragment and had the same issue. I tried all variants from this answers, but the problem wasn't solved.

So I found my variant, to override setEmptyText():

public class NewsFragment extends ListFragment{
    private TextView emptyText;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
        //...

        emptyText = (TextView)view.findViewById(android.R.id.empty);

        //...
    }

    @Override
    public void setEmptyText(CharSequence text) {
        emptyText.setText(text);
    }
}

Hope it will be helpful for somebody.

Finegrained answered 5/3, 2014 at 15:3 Comment(0)
T
4

I know this is kind of late, but for it to work from XML, you need to put a weight on your ListView and have your TextView match_parent

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

<ListView
    android:id="@android:id/list"
    android:layout_width="wrap_content"
    android:layout_height="0dp"
    android:layout_weight="1"
    android:dividerHeight="1dp" >
</ListView>

<TextView 
    android:id="@android:id/empty"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:text="@string/empty_list" />

</LinearLayout>
Travelled answered 26/6, 2014 at 6:47 Comment(0)
P
3

There's a good example of how to do it which works awesome:

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”.

  1. 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>
  1. Create an xml for displaying items (when the list is not empty), and name it “list_item”.

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

  2. 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;
    
    }
    }
    
  3. 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));
     }
     }
    
Parsee answered 27/1, 2018 at 17:44 Comment(0)
S
0
 TextView tv=(TextView) view.findViewById(R.id.empty);
 tv.setVisibiliy(View.GONE);
Squalene answered 25/4, 2020 at 5:26 Comment(1)
Code-only answers are not particularly helpful. Please include a brief description of how this code solves the problem.Holyhead

© 2022 - 2024 — McMap. All rights reserved.