Hide footer view in ListView?
Asked Answered
E

13

78

I have a ListView. The data behind it is fetched from the Internet, in sets of 10-30 items whenever the user scrolls all the way to the bottom. In order to indicate that it is loading more items, I used addFooterView() to add a simple view that displays a "Loading..." message and a spinner. Now, when I'm out of data (no more data to fetch), I want to hide that message. I tried to do:

loadingView.setVisibility(View.GONE);

Unfortunately, while that does hide the view, it leaves space for it. I.e. I end up with a big blank space where the "Loading" message used to be. How can I go about properly hiding this view?

I can't use removeFooterView() because I may need to show it again, in which case I can't call addFooterView() again because an adapter has already been set on the ListView, and you can't call addHeaderView() / addFooterView() after setting an adapter.

Emotion answered 30/11, 2010 at 19:40 Comment(0)
E
84

It seems that you are allowed to call addHeaderView() / addFooterView() after setAdapter() as long as you call one of those methods at least once before. That is a rather poor design decision from Google, so I filed an issue. Combine this with removeFooterView() and you have my solution.

+1 for the other two answers I got, they're valid (and arguably more correct) solutions. Mine, however, is the simplest, and I like simplicity, so I'll mark my own answer as accepted.

Emotion answered 30/11, 2010 at 21:33 Comment(6)
This doesn't appear to work for Headers. I can add a footer after setAdapter, but not a header.Merlynmermaid
+1 for saving a HUGE headache. I wonder how long it would have taken me to figure out you had to add the footer before setting the adapter. (dumb)Diapause
I've noticed that the scrolling position gets reset when you remove the bottom one, so when you're overscrolling -> footer is removed before you finish overscrolling, it jumps back to the end of the list. Did you run into this?Mchale
Nevermind, I ran into the same issue as littleFluffyKitty did. Going to have to go with a custom adapter.Mchale
Great answer, simple! +100 for filing the issues with Google.Mulley
Finally Google fixed this on Android 4.4 KitKat.Dowable
D
37

Try setting the footer's height to 0px or 1px before hiding it. Alternatively, wrap the footer view in a wrap_content height FrameLayout and hide/show the inner view, leaving the FrameLayout visible; the height should wrap properly then.

Disputatious answered 30/11, 2010 at 19:47 Comment(3)
How do you force set the height of the view? I tried setMinimumHeight(0); before hiding but doesn't seem to work. I've set it to GONE but the space of the cell is still left behind.Borchert
The height and width are layout parameters, so you have to set the LayoutParameters object for the view with the new width/height. See this SO answer: https://mcmap.net/q/266273/-android-ignoring-my-setwidth-and-setheight. Basically, width, height and margins are properties that really apply to the view's container, not the view itself, so you use a parent-linked LayoutParameter object to define them.Disputatious
I don't think that works for a header, I got null on a header that was attached and called getLayoutParams() for.Mchale
H
5

in my case addFooterView / removeFooterView() cause some artefacts. And I found other solution. I used FrameLayout as FooterView. And when I want to add Footer I called mFrameFooter.addView(myFooter); and mFrameFooter.removeAllViews(); for remove.

FrameLayout frameLayout = new FrameLayout(this);
listView.addFooterView(frameLayout);
......
......
//For adding footerView
frameLayout.removeAllViews();
frameLayout.addView(mFooterView);
//For hide FooterView
frameLayout.removeAllViews();
Halogenate answered 23/4, 2014 at 7:55 Comment(1)
Working like a charm. It should be the accepted answer :)Supposal
A
4

The Droid-Fu library has a class designed for having a loading footer show and hide: ListAdapterWithProgress.

Asta answered 30/11, 2010 at 19:49 Comment(1)
With a usage example, this answer would have gained more votes.Nyasaland
H
4

Works well in my project:

1.Add footer view first

mListView.addFooterView(mFooterView); mListView.setAdapter(mAdapter);

2.Set visibility

mFooterView.setVisibility(View.GONE); mFooterView.setPadding(0, 0, 0, 0);

3.Set invisibility

mFooterView.setVisibility(View.GONE); mFooterView.setPadding(0, -1*mFooterView.getHeight(), 0, 0);

Hapte answered 13/11, 2014 at 8:56 Comment(0)
F
2

As @YoniSamlan pointed out, it can be achieved in a simple way. You have to specify

android:layout_height="wrap_content" 

in the ViewGroup that contains the "Load More" button. Doesn't have to be FrameLayout, see below for a simple -working- example that uses a LinearLayout.

Both images show a screen that is scrolled all the way to the bottom. First one has a visible footer that wraps around the "load more" button. Second images shows that the footer collapses if you set button's visibility to GONE.

You can show again the footer (inside some callback) by changing the visibility:

loadMore.setVisibility(View.VISIBLE);  // set to View.GONE to hide it again

listView with visible footer listView with footer gone

Perform listView initialization as usual

    // Find View, set empty View if needed
    mListView = (ListView) root.findViewById(R.id.reservations_search_results);
    mListView.setEmptyView(root.findViewById(R.id.search_reservations_list_empty));

    // Instantiate footerView using a LayoutInflater and add to listView
    footerView = ((LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE))
            .inflate(R.layout.load_more_footer_view, null, false);
    // additionally, find the "load more button" inside the footer view
    loadMore = footerView.findViewById(R.id.load_more);
    loadMore.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            fetchData();
        }
    });

    // add footer view to the list
    mListView.addFooterView(footerView);

    // after we're done setting the footerView, we can setAdapter
    adapter = new ReservationsArrayAdapter(getActivity(), R.layout.list_item_reservations_search, reservationsList);
    mListView.setAdapter(adapter);

load_more_footer_view.xml

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

<Button
    android:id="@+id/load_more"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="9dp"
    android:gravity="center"
    android:layout_gravity="center"
    android:background="@drawable/transparent_white_border"
    android:textColor="@android:color/white"
    android:text="@string/LOAD_MORE"/>

Fidler answered 11/9, 2014 at 16:18 Comment(0)
F
2

It should be a bug of Android.

You don't need to remove or add footer view dynamically. You just need to create an unspecified height parent Layout (either inflate it from an xml file or create it programatically) and then add your view which you want to hide or show into it.

And you can set the view, but NOT the parent Layout, to VISIBLE or GONE or something else now. It works for me.

Favoritism answered 20/9, 2014 at 15:38 Comment(0)
U
0

Used

footer.removeAllViews();

This does not remove footer but flushes children. You again have to repopulate children. Can check by

footer.getChildCount()<2
Uncompromising answered 9/1, 2011 at 12:33 Comment(0)
S
0

I also found that is possible call onContentChanged() (if you use ListActivity) to force recreate ListView if I need add HeaderView to them after setAdapter() call, but it is very ugly hack.

Selfesteem answered 23/1, 2011 at 10:38 Comment(0)
H
0

I have created a ListView that handles this. It also has an option to use the EndlessScrollListener I've created to handle endless listviews, that loads data until there's no more data to load.

You can see these classes here:

https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/helper/ListViewWithLoadingIndicatorHelper.java - Helper to make it possible to use the features without extending from SimpleListViewWithLoadingIndicator.

https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/listener/EndlessScrollListener.java - Listener that starts loading data when the user is about to reach the bottom of the ListView.

https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/view/SimpleListViewWithLoadingIndicator.java - The EndlessListView. You can use this class directly or extend from it.

Hellenic answered 14/6, 2013 at 14:0 Comment(0)
A
0

I have small hack way to resolve this problem for everywhere. Put listview and footer view (just sub layout) in parent layout like LinnearLayout, remember that footerview below listview.

Controller this footer view gone and visibility like nomal view. And done!

Alyce answered 3/10, 2014 at 6:56 Comment(0)
B
0

first I am adding my footer to the listview,like this

listView.addFooterView(Utils.b);

Then on button click , I remove the view,

listView.removeFooterView(Utils.b);

I am adding the footer everytime when I am hitting the async,and theus the're no duplicate entry.I could aslo check for the count and so it like this,

if(listView.getFooterViewsCount() > 0){//if footer is added already do something}
Boney answered 3/3, 2017 at 2:41 Comment(0)
N
-1

When you want to remove the footer in ListView just call

listView.addFooterView(new View(yourContext)); 

It will add a dummy empty view which will not reserve any space

Natividad answered 25/9, 2012 at 9:0 Comment(1)
documentation says "If addFooterView is called more than once, the views will appear in the order they were added."Gustavo

© 2022 - 2024 — McMap. All rights reserved.