Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android - SwipeRefreshLayout with empty textview

I've implemented SwipeRefreshLayout into my app but it can only hold one direct child which should be the listview. I'm trying to figure out how to add an empty textview to the following working XML file:

<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/swipe_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

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

</android.support.v4.widget.SwipeRefreshLayout>

Wrapping it in a Linear/Relative layout makes it buggy because the listview will always update when you want to slide back up the listview. One way I can think of is doing this programmatically but I guess that's not the best option.

You can learn how to implement it using this tutorial: Swipe to refresh GUIDE

So basically it all works fine but I would like to add an empty view that shows a message when the listview is empty.

like image 923
Niels Avatar asked Apr 09 '14 13:04

Niels


2 Answers

I didn't liked the limitation to a single child. Furthermore the current implementation of the SwipeRefreshLayout has an hardcoded "magic" handling for ScrollView, ListView and GridView that trigger only if the view it's the direct child of your own view.

That said the good news it's that it is open source, so you can either copy the code and adapt to your needs or you can do what I did:

Use two DIFFERENT SwipeRefreshLayout, one for the Empty view and one for the ListView.

<FrameLayout 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"     tools:context="com.tobrun.example.swipetorefresh.MainActivity">      <android.support.v4.widget.SwipeRefreshLayout         android:id="@+id/swipeRefreshLayout_listView"         android:layout_width="match_parent"         android:layout_height="match_parent">          <ListView             android:id="@+id/listView"             android:layout_width="match_parent"             android:layout_height="wrap_content" />      </android.support.v4.widget.SwipeRefreshLayout>      <android.support.v4.widget.SwipeRefreshLayout         android:id="@+id/swipeRefreshLayout_emptyView"         android:layout_width="match_parent"         android:layout_height="match_parent">          <ScrollView             android:layout_width="match_parent"             android:layout_height="match_parent"             android:fillViewport="true">              <TextView                 android:id="@+id/emptyView"                 android:text="@string/empty"                 android:layout_width="match_parent"                 android:layout_height="wrap_content"                 android:layout_gravity="center"                 android:gravity="center" />          </ScrollView>      </android.support.v4.widget.SwipeRefreshLayout>   </FrameLayout> 

Then tell your listview that the empty list view is the swipe refresh layout of the empty view.

Now the empty refresh layout will be automatically hidden by your list view when you have data and will be shown when the list is empty.

The swipe refresh layout of the list shouldn't receive touch events cause the list is hidden.

Good luck.

like image 124
Daniele Segato Avatar answered Sep 17 '22 15:09

Daniele Segato


There is no need for any workaround.

You can simply use this view hierarchy :

    <FrameLayout ...>

        <android.support.v4.widget.SwipeRefreshLayout ...>

            <ListView
                android:id="@android:id/list" ... />
        </android.support.v4.widget.SwipeRefreshLayout>

        <TextView
            android:id="@android:id/empty" ...
            android:text="@string/empty_list"/>
    </FrameLayout>

Then, in code, you just call:

_listView.setEmptyView(findViewById(android.R.id.empty));

That's it.


EDIT: If you wish to be able to swipe-to-refresh even when the empty view is shown, you will have to somehow avoid hiding the ListView, so you could use a customized ListView that has this function inside:

@Override
  public void setVisibility(final int visibility)
    {
    if(visibility!=View.GONE||getCount()!=0)
      super.setVisibility(visibility);
    }

Together with the solution I wrote, the swipe-to-refresh is shown no matter how many items you are showing.

Of course, if you really want to hide the ListView, you should change the code. Maybe add "setVisibilityForReal(...)" :)

like image 30
android developer Avatar answered Sep 16 '22 15:09

android developer