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 emp
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.
As i mentioned here, i have done this for RecyclerView
:
I have used clickable="true"
like below with empty RecyclerView
:
mRecyclerView.setVisibility(View.VISIBLE);
mRecyclerView.setClickable(true);
myText.setVisibility(View.VISIBLE);
xml layout:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipeRefreshKartvizitKisilerim"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.v4.widget.SwipeRefreshLayout>
<TextView
android:id="@+id/myText"
android:visibility="gone"
android:text="@string/noListItem"
android:textSize="18sp"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
RecyclerView
has height match_parent
and SwipeRefresh
has wrap_content
. When there is item in list, don't forget to make text gone
.
This worked for me
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/lighter_white">
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipeContainer"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:background="@color/silver"
android:layout_marginTop="10dp"
android:divider="@android:color/transparent"
android:dividerHeight="8dp"
android:padding="4dp"/>
</android.support.v4.widget.SwipeRefreshLayout>
<TextView
android:id="@+id/empty"
android:text="@string/strNoRecordsFound"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textColor="@android:color/black"
android:alpha="0.5"
android:gravity="center">
</TextView>
</FrameLayout>
Probably late, But if you're still facing this issue, Here is the clean solution! There is no need of creating another SwipeRefreshLayout
.
wrap empty view
into a ScrollView
. Stick both AdapterView
and the ScrollView
into a ViewGroup
and put it into the SwipeRefreshLayout
Sample:
<android.support.v4.widget.SwipeRefreshLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center" />
</ScrollView>
</FrameLayout>
</android.support.v4.widget.SwipeRefreshLayout>
EDIT
Here is much more simpler way.
check if your list is empthy. if yes then make it invisible. Sample:
if(lst.size() > 0) {
mRecyclerView.setVisibility(View.VISIBLE);
//set adapter
}else
{
mRecyclerView.setVisibility(View.INVISIBLE);
findViewById(R.id.txtNodata).setVisibility(View.VISIBLE);
}
this will make mRecyclerView
still there and all swipes will be working fine now even there is no data!
Put SwipeRefreshLayout into a FrameLayout and other views behind it.
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:id="@+id/your_message_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="No result"/>
</LinearLayout>
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipe_container"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ListView
android:id="@+id/your_list_view"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ListView>
</android.support.v4.widget.SwipeRefreshLayout>
</FrameLayout>
I have tried following thing. In both empty view, and case of a list, swipe will refresh the data, also fastscroll is working fine without any code change required in activity. I have put emptyview before the listview and marked its visiblity to gone. and listview is put after that inside SwipeToRefresh block. Sample Code -
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<TextView
android:id="@+id/tv_empty_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="32dp"
android:gravity="center_horizontal"
android:text="No item found"
android:visibility="gone"/>
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipe"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@+id/lv_product"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.widget.SwipeRefreshLayout>
</FrameLayout>