Scroll up does not work with SwipeRefreshLayout in Listview Scroll up does not work with SwipeRefreshLayout in Listview android android

Scroll up does not work with SwipeRefreshLayout in Listview


In order for SwipeRefreshLayout to work, it needs to be the direct parent of your ListView, and the ListView should be the first active child view of the SwipeRefreshLayout.

The documentation for SwipeRefreshLayout says that the ListView should be the only child, but it is okay if it has more than one child as long as the ListView is first. This means, for instance, that SwipeRefreshLayout will work fine if you are using an adapter with a view for "empty". For example:

<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:id="@+id/swipe_refresh"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context=".NearbyJobsActivity$PlaceholderFragment">    <ListView        android:id="@android:id/list"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:divider="@color/list_divider"        android:dividerHeight="1dp"        android:listSelector="@drawable/list_row_selector" />    <TextView        android:id="@android:id/empty"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:gravity="center" /></android.support.v4.widget.SwipeRefreshLayout>

If you can manage this sort of layout, then SwipeRefreshLayout will work fine and you won't need any of the workarounds listed in other answers.

My own problem was that that I was loading my ListView as a Fragment, so I actually had:

<SwipeRefreshLayout>    <FrameLayout>           )         <ListView/>        \ fragment         <TextView/>        /    </FrameLayout>          )</SwipeRefreshLayout>

So the SwipeRefreshLayout was choosing the FrameLayout as it's "target" and its default canChildScrollUp() implementation was always returning false. Once I moved the SwipeRefreshLayout inside the Fragment, everything started working correctly.

<FrameLayout>    <SwipeRefreshLayout>    )         <ListView/>        \ fragment         <TextView/>        /    </SwipeRefreshLayout>   )</FrameLayout>


I had the same problem and solved it:

listView = (ListView) findViewById(R.id.listView);listView.setOnScrollListener(new AbsListView.OnScrollListener() {    @Override     public void onScrollStateChanged(AbsListView view, int scrollState) {    }    @Override    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {        if (listView.getChildAt(0) != null) {        swipeRefreshLayout.setEnabled(listView.getFirstVisiblePosition() == 0 && listView.getChildAt(0).getTop() == 0);        }    }});


Create a layout like this one.

<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"><LinearLayout    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="@string/guides_no_results"        android:id="@+id/empty_view"        android:gravity="center"        android:padding="16dp"        android:fontFamily="sans-serif-light"        android:textSize="20sp"        android:visibility="gone"/>    <ListView        android:layout_width="match_parent"        android:layout_height="match_parent"        android:drawSelectorOnTop="true"        android:divider="@android:color/transparent"        android:dividerHeight="0dp"        android:id="@+id/guides_list" /></LinearLayout>

If you use this as-is, everytime you scroll up in that view, the SwipeRefreshLayout fires and updates, making your app unable to scroll up in a list.

The trick here is to wire the OnScrollListener from the ListView manually. You just check if the first row being shown matches the first top-most position, and then enable the SwipeRefreshLayout. Otherwise, disable it.

guidesList.setOnScrollListener(new AbsListView.OnScrollListener(){      @Override    public void onScrollStateChanged(AbsListView view, int scrollState)    {    }    @Override    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)    {        int topRowVerticalPosition = (guidesList == null || guidesList.getChildCount() == 0) ? 0 : guidesList.getChildAt(0).getTop();        swipeContainer.setEnabled(firstVisibleItem == 0 && topRowVerticalPosition >= 0);    }});

With this little snippet now it works perfectly.

Happy coding!

Source - http://nlopez.io/swiperefreshlayout-with-listview-done-right/