滚动位置位于顶部时,SwipeRefreshLayout + WebView

我正在尝试将SwipeRefreshLayout与WebView一起使用。

我面临的问题是在页面中间,当用户向下滚动时,不必要的刷新开始。

如何在webview的滚动位置位于顶部时才进行刷新事件。 (即,他正在查看页面的顶部)?

我认为推荐的方法是扩展SwipeRefreshLayout并覆盖canChildScrollUp()https://developer.android.com/reference/android/support/v4/widget/SwipeRefreshLayout.html#canChildScrollUp()

这就是在Google IO 2014计划应用中完成的操作 – https://github.com/google/iosched/blob/master/android/src/main/java/com/google/samples/apps/iosched/ui/widget /MultiSwipeRefreshLayout.java#L76

CustomSwipeRefreshLayout可能如下所示:

 public class CustomSwipeRefreshLayout extends SwipeRefreshLayout { private CanChildScrollUpCallback mCanChildScrollUpCallback; public interface CanChildScrollUpCallback { boolean canSwipeRefreshChildScrollUp(); } public void setCanChildScrollUpCallback(CanChildScrollUpCallback canChildScrollUpCallback) { mCanChildScrollUpCallback = canChildScrollUpCallback; } @Override public boolean canChildScrollUp() { if (mCanChildScrollUpCallback != null) { return mCanChildScrollUpCallback.canSwipeRefreshChildScrollUp(); } return super.canChildScrollUp(); } } 

在您的具有WebView Activity中,

 public class FooActivity implements CustomSwipeRefreshLayout.CanChildScrollUpCallback { private CustomSwipeRefreshLayout mRefreshLayout; private WebView mWebView; @Override protected void onCreate(Bundle savedInstanceState) { // after initialization mRefreshLayout.setCanChildScrollUpCallback(this); } @Override public boolean canSwipeRefreshChildScrollUp() { return mWebview.getScrollY() > 0; } } 

我设法解决它而不必扩展任何东西。 看看这个片段(特定于片段):

 private ViewTreeObserver.OnScrollChangedListener mOnScrollChangedListener; @Override public void onStart() { super.onStart(); swipeLayout.getViewTreeObserver().addOnScrollChangedListener(mOnScrollChangedListener = new ViewTreeObserver.OnScrollChangedListener() { @Override public void onScrollChanged() { if (mWebView.getScrollY() == 0) swipeLayout.setEnabled(true); else swipeLayout.setEnabled(false); } }); } @Override public void onStop() { swipeLayout.getViewTreeObserver().removeOnScrollChangedListener(mOnScrollChangedListener); super.onStop(); } 

有关更广泛的背景,请查看我对Android的答案- 使用空textview的SwipeRefreshLayout 。

只需使用ViewTreeObserver.OnScrollChangedListener实现FragmentActivity ,然后设置Listener,如webview.getViewTreeObserver().addOnScrollChangedListener(this);

onScrollChanged()方法中这样做

  @Override public void onScrollChanged() { if (webview.getScrollY() == 0) { swipeLayout.setEnabled(true); } else { swipeLayout.setEnabled(false); } } 

您可以通过使用自定义SwipeRefreshLayout扩展SwipeRefreshLayout来解决此问题,该自定义SwipeRefreshLayout接收WebView并使用WebView检查scrollY位置。

注意:这将用于滚动整个页面,但它可能不适用于嵌套滚动。 此外,如果您有水平滚动,您可能还想添加此答案中的逻辑: https : //stackoverflow.com/a/24453194

 public class CustomSwipeToRefresh extends SwipeRefreshLayout { private final int yScrollBuffer = 5; private WebView mWebView; public CustomSwipeToRefresh(Context context, WebView webView) { super(context); mWebView = webView; } @Override public boolean onInterceptTouchEvent(MotionEvent event) { if (mWebView.getScrollY() > yScrollBuffer) return false; return super.onInterceptTouchEvent(event); } } 

我面临类似的问题,但这里给出的答案都不适合我。 所以,我从这个答案得到了解决方案。

第1步 :创建类CustomWebView

 public class CustomWebView extends WebView{ private OnScrollChangedCallback mOnScrollChangedCallback; public CustomWebView(final Context context) { super(context); } public CustomWebView(final Context context, final AttributeSet attrs) { super(context, attrs); } public CustomWebView(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); } @Override protected void onScrollChanged(final int l, final int t, final int oldl, final int oldt) { super.onScrollChanged(l, t, oldl, oldt); if(mOnScrollChangedCallback != null) mOnScrollChangedCallback.onScroll(l, t); } public OnScrollChangedCallback getOnScrollChangedCallback() { return mOnScrollChangedCallback; } public void setOnScrollChangedCallback(final OnScrollChangedCallback onScrollChangedCallback) { mOnScrollChangedCallback = onScrollChangedCallback; } /** * Impliment in the activity/fragment/view that you want to listen to the webview */ public static interface OnScrollChangedCallback { public void onScroll(int horizontal, int vertical); }} 

第2步 :在xml文件中使用像这样的webview-

   

第3步 :在MainActivity使用setOnScrollChangedCallback

  mWebView.setOnScrollChangedCallback(new CustomWebView.OnScrollChangedCallback(){ public void onScroll(int horizontal, int vertical){ System.out.println("=="+horizontal+"---"+vertical); //this is to check webview scroll behaviour if (vertical<50){ swipeRefreshLayout.setEnabled(true); }else{ swipeRefreshLayout.setEnabled(false); } } }); } 

hiBrianLee提供的答案几乎对我有用,但正如John Shelley写的那样, getScrollY在我的情况下总是返回0(我使用ListView作为嵌套的滚动子项)。 然而,直接使用的是使用canScrollVertically (这是一种View方法,因此它既可用于ListViewWebView ,也可用于任何其他types的滚动子)。

我的布局类看起来如下:

 public class NestedScrollSwipeLayout extends SwipeRefreshLayout { private ListView scrollChild; public NestedScrollSwipeLayout(Context context) { super(context); } public NestedScrollSwipeLayout(Context context, AttributeSet attrs) { super(context, attrs); } public void setScrollChild(ListView child) { this.scrollChild = child; } @Override public boolean canChildScrollUp() { return (scrollChild != null && scrollChild.canScrollVertically(-1)) || super.canChildScrollUp(); } } 

(如前所述, canScrollVertically是一个View方法,因此可以通过一般View或任何其他专用视图类安全地替换ListView 。)

正常使用SwipeRefreshLayout,就像使用其他视图一样,但启用嵌套滚动。

 swipeRefreshLayout.setNestedScrollingEnabled(true); 

我find了解决方案。 只需使用CoordinatorLayout作为根布局,并将layout_behavior =“@ string / appbar_scrolling_view_behavior”添加到您的SwipeRefreshLayout.It对我来说非常适合。

我发现在webview禁用嵌套滚动(而不是SwipeRefreshLayout本身)为我排序了这个问题。 在所有情况下都不可能做到这一点,但在我的情况下。

 webView.setNestedScrollingEnabled(false);