在Listview中向上滚动不适用于SwipeRefreshLayout

我想实现滚动来刷新ListView的function。 同样的布局文件中还有其他视图元素,如果列表是空的,则显示这些元素。 这是我的布局文件。 问题是,当我向下滚动,然后尝试向上滚动,而不是一直滚动到顶部,然后刷新它只刷新那里和向上滚动不起作用。

<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_container" android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" > <RelativeLayout android:layout_width="wrap_content" android:layout_height="64dp" android:paddingLeft="16dp" android:paddingRight="16dp" > <ImageView android:layout_width="40dp" android:layout_height="40dp" android:layout_alignParentLeft="true" android:layout_centerVertical="true" android:src="@drawable/inbox_empty" /> <TextView android:id="@+id/noEventsText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginLeft="16dp" android:layout_toRightOf="@+id/noEventsIcon" /> <View android:id="@+id/divider" android:layout_width="match_parent" android:layout_height="1px" android:layout_alignParentBottom="true" android:layout_marginLeft="4dp" android:layout_marginRight="4dp" android:background="@color/dividerOnBlack" /> </RelativeLayout> <ListView android:id="@+id/list_items" android:layout_width="match_parent" android:layout_height="fill_parent" android:cacheColorHint="@android:color/transparent" android:choiceMode="multipleChoice" android:descendantFocusability="afterDescendants" android:divider="@android:color/transparent" android:dividerHeight="0px" android:scrollbars="none" /> </LinearLayout> </android.support.v4.widget.SwipeRefreshLayout> 

这是我的onScroll方法。

 @Override public void onScroll(AbsListView view,int firstVisibleItem,int visibleItemCount,int totalItemCount) { // If the total item count is zero and the previous isn't, assume the // list is invalidated and should be reset back to initial state if (totalItemCount < previousTotalItemCount) { this.currentPage = this.startingPageIndex; this.previousTotalItemCount = totalItemCount; if (totalItemCount == 0) { this.loading = true; } } // If it's still loading, we check to see if the dataset count has // changed, if so we conclude it has finished loading and update the current page // number and total item count. if (loading && (totalItemCount > previousTotalItemCount)) { loading = false; previousTotalItemCount = totalItemCount; currentPage++; } // If reverse then the firstVisibleItem is calculated wrong if (reverse) { firstVisibleItem = totalItemCount - firstVisibleItem; } // If it isn't currently loading, we check to see if we have breached // the visibleThreshold and need to reload more data. // If we do need to reload some more data, we execute onLoadMore to fetch the data. if (!loading && (totalItemCount - visibleItemCount)<=(firstVisibleItem + visibleThreshold)) { onLoadMore(currentPage + 1, totalItemCount); loading = true; } } 

Solutions Collecting From Web of "在Listview中向上滚动不适用于SwipeRefreshLayout"

为了使SwipeRefreshLayout正常工作,它需要是ListView的直接父项,ListView应该是SwipeRefreshLayout的第一个活动子视图。

SwipeRefreshLayout的文档说ListView应该是唯一的孩子,但是如果它有多个孩子,只要ListView是第一个就可以了。 这意味着,例如,如果您使用视图为“空”的适配器,SwipeRefreshLayout将正常工作。 例如:

 <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> 

如果您可以pipe理这种布局,那么SwipeRefreshLayout将正常工作,您不需要在其他答案中列出的任何解决方法。

我自己的问题是,我正在加载我的ListView作为一个片段,所以我其实:

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

所以SwipeRefreshLayoutselect了FrameLayout,因为它是“target”,它的默认的canChildScrollUp()实现总是返回false。 一旦我移动片段内的SwipeRefreshLayout,一切都开始正常工作。

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

创build一个这样的布局。

 <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> 

如果按原样使用,则每次在该视图中向上滚动时,SwipeRefreshLayout都会触发并更新,使您的应用无法在列表中向上滚动。

这里的技巧是手动连接ListView中的OnScrollListener。 您只需检查显示的第一行是否与第一个最顶端的位置匹配,然后启用SwipeRefreshLayout。 否则,禁用它。

 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); } }); 

有了这个小片段,现在它完美的工作。

快乐的编码!

来源 – http://nlopez.io/swiperefreshlayout-with-listview-done-right/

我有同样的问题,解决了它:

 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); } } }); 

制作您自己的SwipeRefreshLayout实现,并以这种方式覆盖canChildScrollUp:

 @Override public boolean canChildScrollUp() { if (scrollView != null) return scrollView.canScrollVertically(-1); return false; } 

只需replace为ScrollView的任何子类。

我有一个类似的问题,我的SwipeRefreshLayout的孩子是一个FrameLayout有一个TextViewListView作为孩子,当我滚动在ListView上,它会尝试刷新。

我通过使用覆盖canScrollVertically()方法的自定义FrameLayout来修复它

包com.wi.director.ui.common;

 import android.content.Context; import android.util.AttributeSet; import android.widget.FrameLayout; /** * Created by devansh on 9/22/15. */ public class FrameLayoutForSwipeRefresh extends FrameLayout { public FrameLayoutForSwipeRefresh(Context context) { super(context); } public FrameLayoutForSwipeRefresh(Context context, AttributeSet attrs) { super(context, attrs); } public FrameLayoutForSwipeRefresh(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } public boolean canScrollVertically(int direction) { if (super.canScrollVertically(direction)) { return true; } int cc = getChildCount(); for (int i = 0; i < cc; i++) { if (getChildAt(i).canScrollVertically(direction)) { return true; } } return false; } } 

甚至更简单的设置SwipeRefreshLayout 如果 firstVisibleItem或禁用,如果不是:

 yourList.setOnScrollListener(new AbsListView.OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { yourSwipeRefreshLayout.setEnabled(firstVisibleItem == 0); } });