当滚动位置在顶部时,SwipeRefreshLayout + WebView

我正在试图与WebView使用SwipeRefreshLayout。

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

如何使刷新事件只发生在webview的滚动位置在顶部。 (即,他正在看页面的顶部)?

Solutions Collecting From Web of "当滚动位置在顶部时,SwipeRefreshLayout + WebView"

我已经设法解决它,而无需扩展任何东西。 看看这个片段(片段特定):

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的答案- SwipeRefreshLayout与空的textview 。

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

Google IO 2014 Schedule应用程序就是这样做的 – 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(); } } 

而在你的ActivityWebView

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

只需用ViewTreeObserver.OnScrollChangedListener实现你的FragmentActivity ,然后像webview.getViewTreeObserver().addOnScrollChangedListener(this);一样设置监听器webview.getViewTreeObserver().addOnScrollChangedListener(this);

onScrollChanged()方法是这样的

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

你可以通过扩展SwipeRefreshLayout来解决这个问题,这个SwipeRefreshLayout需要接收WebView并使用WebView来检查scrollY的位置。

注意:这将用于滚动整个页面,但它可能不适用于嵌套滚动。 另外,如果你有水平滚动,你可能还想添加这个答案中find的逻辑: 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); } } 

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

第1步 :创build类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像这样 –

  <com.yourpackagename.CustomWebView android:id="@+id/webview" android:layout_width="match_parent" android:layout_height="match_parent"/> 

第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提供的答案几乎为我工作,但正如约翰·雪莱写道, 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方法,所以ListView可以被一个普通的View或任何其他专门的视图类安全地replace。)

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

 swipeRefreshLayout.setNestedScrollingEnabled(true); 

我find了一个解决scheme。 只需使用CoordinatorLayout作为根布局,并向您的SwipeRefreshLayout添加layout_behavior =“@ string / appbar_scrolling_view_behavior”,这对我来说是完美的。

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

 webView.setNestedScrollingEnabled(false);