Correct use of setEmtpyView in AdapterView

26,633

Solution 1

You need to add this same view in the layout in which you have added the AdapterView.

AdapterView only changes its visibility based on the contents in the adapter.

EDITED :
Following layout and code works fine :


<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:layout_width="fill_parent"
        android:layout_height="300dip"
        android:id="@+id/list_view" />
    <TextView
        android:id="@+id/empty_list_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="List view is empty"
        android:visibility="gone" />
</LinearLayout>

Code :

ListView listView = (ListView) findViewById( R.id.list_view );
listView.setEmptyView( findViewById( R.id.empty_list_view ) );
listView.setAdapter( new ArrayAdapter( this, R.layout.selected_spinner_view, new ArrayList() ) );

Solution 2

Karan's answer is spot-on. The AdapterView indeed displays the empty view by merely changing its own visibility vs the empty view's visibility. However, the empty view layout does not necessarily need to be in the same XML file as that of the AdapterView. I found it useful to separate the two because I use a single layout XML file (containing a GridView) for multiple activities, but I wanted to specify different emptyView layouts for each of them.

The key is to add the empty view to the activity with addContentView. Remember to do this after you have called setContentView specifying your main AdapterView.

My code (in AbstractBaseActivity.onCreate) :

View mainView = inflater.inflate(R.layout.imagegrid, null);
GridView gridView = (GridView)mainView.findViewById(R.id.gridView);
View emptyView = inflater.inflate(getIdOfEmptyView(), null, false);
gridView.setEmptyView(emptyView);
// Any additional processing on mainView
setContentView(mainView);
addContentView(emptyView, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));

In each child activity I override getIdOfEmptyView as follows:

@Override
protected int getIdOfEmptyView()
{
    return R.layout.emptyView_Favorites;
}

Solution 3

You can define external XML layout files, inflate and set it as an empty view. Only thing to remember is to set the parent of the inflated view.

View emptyView = inflater.inflate(R.layout.id_of_your_layoout_file, parent, false);
gridView.setEmptyView(emptyView);

or

listView.setEmptyView(emptyView);
Share:
26,633
RoflcoptrException
Author by

RoflcoptrException

Updated on January 16, 2020

Comments

  • RoflcoptrException
    RoflcoptrException over 4 years

    I'm really having trouble using the setEmptyView method. I tried it to implement it in GridView and ListView, but both of them didnt work. Here a sample codeblock:

     networkGames = (GridView) baseLayer.findViewById(R.id.all_game_grid_network);
     networkGames.setBackgroundResource(R.drawable.game_border);
     networkGames.setSelector(R.drawable.game_active_border);
     networkGames.setOnItemClickListener(new NetworkGameListener());
     networkGames.setEmptyView(View.inflate(baseLayer, R.drawable.no_network_games, null));
     networkGames.setAdapter(new NetworkAdapter());
    

    The network adapter contains no items:

    private class NetworkAdapter extends BaseAdapter {
    
            /* (non-Javadoc)
             * @see android.widget.Adapter#getCount()
             */
            @Override
            public int getCount() {
                return 0;
            }
    
            /* (non-Javadoc)
             * @see android.widget.Adapter#getItem(int)
             */
            @Override
            public Object getItem(int position) {
                return null;
            }
    
            /* (non-Javadoc)
             * @see android.widget.Adapter#getItemId(int)
             */
            @Override
            public long getItemId(int position) {
                return 0;
            }
    
            /* (non-Javadoc)
             * @see android.widget.Adapter#getView(int, android.view.View, android.view.ViewGroup)
             */
            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                return null;
            }
    
        }
    

    I also tried to call networkGames.setAdapter(null), but this doesnt work either. My emtpyView looks like this:

    <LinearLayout
    android:id="@+id/LinearLayout01"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    xmlns:android="http://schemas.android.com/apk/res/android">
        <TextView
        android:text="There are currently no network games available. Start a new one."
        android:id="@+id/TextView01"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:gravity="center">
        </TextView>
    </LinearLayout>
    

    I really don't know what I'm doing wrong. I also read various tutorials, but none of them metnioned any problems.

  • RoflcoptrException
    RoflcoptrException about 14 years
    i added the above layout at the end of the layout where i define my gridview. but nevertheless it isn't displayed
  • RoflcoptrException
    RoflcoptrException about 14 years
    hmm is it possible that i have to define the gridview and the emptyview exclusively (with no other layout items like buttons) in a separate xml file?
  • Karan
    Karan about 14 years
    I've modified the answer with the example. It works fine on Android 2.1. HTH !
  • devunwired
    devunwired almost 14 years
    This helped me in a slightly unrelated situation. The fact that AdapterView just changes visibility instead of actually managing which View is presents to its parent layout is the key!
  • QuinnVT
    QuinnVT over 11 years
    what if you don't want the whole activity to be overridden with your empty view (like headers or buttons)?
  • PacificSky
    PacificSky over 11 years
    One option might be to wrap both the GridView and whatever empty view you have in a parent layout (like a LinearLayout or RelativeLayout in the activity's view). That will ensure that they occupy at most as much space as the parent. The parent itself could be laid out in the activity view using a RelativeLayout, ensuring that headers, buttons etc are correctly shown independently of the GridView/empty view.
  • Andy
    Andy over 11 years
    Awesome. That addContentView line was exactly what I was missing in my code. Thanks!
  • raksja
    raksja over 8 years
    This doesnt work if you are using android.support.v4.widget.SwipeRefreshLayout
  • RED_
    RED_ over 8 years
    @techastute is there a solution for swiperefreshlayout?
  • TheRealChx101
    TheRealChx101 almost 6 years
    What about for a Spinner and what if you're calling that function outside AdapterView without a parent object? LayoutParams didn't work for me an my Spinner shrinks/disappears when empty.