Android 当滚动位置在顶部时 SwipeRefreshLayout + WebView
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24658428/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
SwipeRefreshLayout + WebView when scroll position is at top
提问by eugene
I'm trying to use SwipeRefreshLayout with WebView.
我正在尝试将 SwipeRefreshLayout 与 WebView 一起使用。
I'm facing the problem where in the middle of page, when user scrolls down, unwanted refresh kicks in.
我面临的问题是在页面中间,当用户向下滚动时,会出现不需要的刷新。
How do I make the refresh event only happen when webview's scroll position is at the top. (ie, he's looking at the top portion of the page)?
如何使刷新事件仅在 webview 的滚动位置位于顶部时发生。(即,他正在查看页面的顶部)?
回答by vizZ
I've managed to solve it without having to extend anything. Have a look at this snippet (Fragment-specific):
我已经设法解决它而无需扩展任何东西。看看这个片段(特定于片段的):
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();
}
For a broader context, have a look at my answer to Android - SwipeRefreshLayout with empty textview.
对于更广泛的上下文,请查看我对Android - SwipeRefreshLayout with empty textview 的回答。
回答by hiBrianLee
I think the recommended way of doing this is to extend the SwipeRefreshLayoutand override canChildScrollUp()- https://developer.android.com/reference/android/support/v4/widget/SwipeRefreshLayout.html#canChildScrollUp()
我认为这样做的推荐方法是扩展SwipeRefreshLayout和覆盖canChildScrollUp()- https://developer.android.com/reference/android/support/v4/widget/SwipeRefreshLayout.html#canChildScrollUp()
This is how it's done in the Google IO 2014 Schedule app - https://github.com/google/iosched/blob/master/android/src/main/java/com/google/samples/apps/iosched/ui/widget/MultiSwipeRefreshLayout.java#L76
这是在 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
The CustomSwipeRefreshLayoutwill probably look like:
的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();
}
}
And in your Activitythat has the WebView,
而在你的Activity那个有WebView,
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;
}
}
回答by Pranav
Just implement your Fragmentor Activitywith ViewTreeObserver.OnScrollChangedListenerthen set Listener like webview.getViewTreeObserver().addOnScrollChangedListener(this);
只要实现你的Fragment或Activity有 ViewTreeObserver.OnScrollChangedListener再设置监听像webview.getViewTreeObserver().addOnScrollChangedListener(this);
In onScrollChanged()method do like this
在onScrollChanged()方法中这样做
@Override
public void onScrollChanged() {
if (webview.getScrollY() == 0) {
swipeLayout.setEnabled(true);
} else {
swipeLayout.setEnabled(false);
}
}
回答by Isaac
You can solve this by extending SwipeRefreshLayout with a custom SwipeRefreshLayout that takes in the WebView and use the WebView to check the scrollY position.
您可以通过使用自定义 SwipeRefreshLayout 扩展 SwipeRefreshLayout 来解决此问题,该自定义 SwipeRefreshLayout 接受 WebView 并使用 WebView 检查 scrollY 位置。
Note: This will work for scrolling the whole page, but it may not work with nested scrolls. Also, if you have horizontal scrolling you may also want to add the logic found in this answer: https://stackoverflow.com/a/24453194
注意:这适用于滚动整个页面,但它可能不适用于嵌套滚动。此外,如果您有水平滚动,您可能还想添加在此答案中找到的逻辑: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);
}
}
回答by Alexey
Most recent versions of support library have SwipeRefreshLayout#setOnChildScrollUpCallbackmethod which allows you to avoid subclassing SwipeRefreshLayout.
支持库的最新版本具有SwipeRefreshLayout#setOnChildScrollUpCallback允许您避免子类化的方法SwipeRefreshLayout。
mBinding.swipeRefreshLayout.setOnChildScrollUpCallback((parent, child) ->
mBinding.webView.getScrollY() > 10);
回答by Xenolion
I am answering the same question but using Kotlin. By enabling swipeRefreshLayoutwhen the scrollY of webViewgets 0:
我正在回答同样的问题,但使用 Kotlin。通过启用swipeRefreshLayout时的scrollYwebView得到0:
Make this variable in your fragment or activity:
在您的片段或活动中创建此变量:
private val onScrollChangedListener = ViewTreeObserver.OnScrollChangedListener{ swipeRefreshLayout.isEnabled = webView.scrollY == 0 }
Then onViewCreated:
然后onViewCreated:
swipeRefreshLayout.viewTreeObserver.addOnScrollChangedListener(onScrollChangedListener)
Then onStop:
然后onStop:
swipeRefreshLayout.viewTreeObserver.removeOnScrollChangedListener(onScrollChangedListener)
From here everything will work well. But if the webpage your are using has a fixed header that does not scroll scrollYwill always be equal to 0. And this solution together with other solution in this page may not work.
从这里一切都会正常进行。但是,如果您使用的网页具有不滚动的固定标题,scrollY则将始终等于0. 并且此解决方案与此页面中的其他解决方案一起可能不起作用。
回答by karanatwal.github.io
I was facing Similar issue but none of the answers given here works for me. So, I got a solution from thisanswer.
我遇到了类似的问题,但这里给出的答案都不适合我。所以,我从这个答案中得到了一个解决方案。
Step 1: Create Class CustomWebView
第 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);
}}
Step 2: In xmlfile use webviewlike this-
第 2 步:在xml文件中webview像这样使用-
<com.yourpackagename.CustomWebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
Step 3: In your MainActivityuse setOnScrollChangedCallback-
第 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);
}
}
});
}
回答by doertsch
The answer provided by hiBrianLee almostworked for me, but as John Shelley wrote, getScrollYalways returned 0 in my case (I used a ListViewas the nested scrolling child). What worked straight away, however, was to use canScrollVerticallyinstead (which is a Viewmethod, so it's available both for ListViews and WebViews, and also for any other kind of scrolling child).
hiBrianLee 提供的答案几乎对我有用,但正如 John Shelley 所写,getScrollY在我的情况下总是返回 0(我使用 aListView作为嵌套滚动子项)。然而,直接起作用的是改为使用canScrollVertically(这是一种View方法,因此它可用于ListViews 和WebViews,也可用于任何其他类型的滚动子项)。
My layout class looks as follows:
我的布局类如下所示:
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();
}
}
(As mentioned, canScrollVerticallyis a Viewmethod, so the ListViewcan be safely replaced by a general Viewor any other specialized view class.)
(如前所述,canScrollVertically是一种View方法,因此ListView可以安全地替换为通用View或任何其他专用视图类。)
回答by Akash Jp
Nothing above worked for me.Here is my approach
以上没有对我有用。这是我的方法
@Override
public boolean dispatchTouchEvent(MotionEvent event)
{
super.dispatchTouchEvent(event);
int x = (int)event.getX();
int y = (int)event.getY();
if(y>800){
swipeRefreshLayout.setEnabled(false);
}else {
swipeRefreshLayout.setEnabled(true);
}
Log.e("yy",""+y);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
}
return false;
}
}
回答by u6517736
i find a solution for it. Just use the CoordinatorLayout as the root layout and add layout_behavior="@string/appbar_scrolling_view_behavior" to your SwipeRefreshLayout.It's perfect for me.
我找到了解决方案。只需使用 CoordinatorLayout 作为根布局并将 layout_behavior="@string/appbar_scrolling_view_behavior" 添加到您的 SwipeRefreshLayout.It 对我来说是完美的。

