I want to implement scroll to refresh functionality with a listView. Also there are other view elements in the same layout file which are displayed if the list is empty. Her
For Xamarin I had the same issue (Scroll up does not work with SwipeRefreshLayout in Listview) and implemented it this way.
public void OnScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
public void OnScrollStateChanged(AbsListView view, [GeneratedEnum] ScrollState scrollState)
{
if(listView.GetChildAt(0) != null)
{
swipeRefreshLayout.Enabled=listView.FirstVisiblePosition==0 && listView.GetChildAt(0).Top==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/
gridView.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 (gridView.getChildAt(0) != null) {
mrefreshlayout.setEnabled(gridView.getFirstVisiblePosition() == 0 && gridView.getChildAt(0).getTop() == 0);
}
}
});
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swiperefreshlayout"
android:layout_height="match_parent"
android:layout_width="match_parent">
<LinearLayout
android:background="#ffffff"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<GridView
android:background="#ffffff"
android:gravity="center"
android:verticalSpacing="2dp"
android:horizontalSpacing="2dp"
android:numColumns="2"
android:id="@+id/grid_view"
android:animateLayoutChanges="true"
android:overScrollMode="always"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<TextView
android:id="@+id/nofieldtv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/adlayout"
android:textColor="#000000"
android:gravity="center"
android:visibility="gone"
android:textSize="16sp"
android:layout_below="@+id/headerLayout"
android:layout_marginTop="2dp">
</TextView>
</LinearLayout>
</android.support.v4.widget.SwipeRefreshLayout>
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);
}
}
});