39

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.

Akram
  • 7,548
  • 8
  • 45
  • 72
RoflcoptrException
  • 51,941
  • 35
  • 152
  • 200

5 Answers5

94

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() ) );
Karan
  • 12,724
  • 6
  • 40
  • 33
  • i added the above layout at the end of the layout where i define my gridview. but nevertheless it isn't displayed – RoflcoptrException May 11 '10 at 12:43
  • 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? – RoflcoptrException May 11 '10 at 13:41
  • I've modified the answer with the example. It works fine on Android 2.1. HTH ! – Karan May 11 '10 at 17:54
  • 6
    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! – devunwired Aug 08 '10 at 13:36
  • 4
    This doesnt work if you are using `android.support.v4.widget.SwipeRefreshLayout` – raksja Oct 05 '15 at 07:06
  • @techastute is there a solution for swiperefreshlayout? – RED_ Dec 10 '15 at 10:30
20

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;
}
PacificSky
  • 3,422
  • 2
  • 25
  • 24
  • what if you don't want the whole activity to be overridden with your empty view (like headers or buttons)? – QuinnVT Oct 12 '12 at 17:57
  • 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. – PacificSky Oct 16 '12 at 16:38
  • 1
    Awesome. That addContentView line was exactly what I was missing in my code. Thanks! – Andy Jan 08 '13 at 21:02
2

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);
skpal202
  • 1,217
  • 1
  • 9
  • 9
  • 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. – TheRealChx101 Sep 22 '18 at 00:24
0

PacificSky's answer got me almost to what I needed, but adding the empty view to the activity with addContentView caused the empty view to remain in the activity's container even after removing the fragment containing the ListView from the activity. Additionally, the slide in menu for the activity displayed under or mixed in with the empty view.

The solution for me was to add the empty view to the container passed in as a parameter to the fragment's onCreateView:

@Override
public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
    mFragmentContainer = container;
    mListView = (ListView) mLayout.findViewById(R.id.list_view);
    mEmptyListView = inflater.inflate(R.layout.empty_list, null, false);
    container.addView(mEmptyListView);
    mListView.setEmptyView(mEmptyListView);
    mListAdapter = new MyListAdapter(getActivity(), mList);
    mListView.setAdapter(mListAdapter);

And remove the empty view from the container in the fragment's onDestroyView:

@Override
public void onDestroyView(){
    super.onDestroyView();
    mFragmentContainer.removeView(mEmptyListView);
}
chipwilson
  • 160
  • 2
  • 9
0

For my case, gridView.setEmptyView(emptyView) was called but it's not show the emptyview. Unless I called gridView.setVisibility(View.VISIBLE), so it appear normally;