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 SwipeRefreshLayout
and 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 CustomSwipeRefreshLayout
will 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 Activity
that 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 Fragment
or Activity
with ViewTreeObserver.OnScrollChangedListener
then 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#setOnChildScrollUpCallback
method 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 swipeRefreshLayout
when the scrollY of webView
gets 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 scrollY
will 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 webview
like 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 MainActivity
use 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, getScrollY
always returned 0 in my case (I used a ListView
as the nested scrolling child). What worked straight away, however, was to use canScrollVertically
instead (which is a View
method, so it's available both for ListView
s and WebView
s, and also for any other kind of scrolling child).
hiBrianLee 提供的答案几乎对我有用,但正如 John Shelley 所写,getScrollY
在我的情况下总是返回 0(我使用 aListView
作为嵌套滚动子项)。然而,直接起作用的是改为使用canScrollVertically
(这是一种View
方法,因此它可用于ListView
s 和WebView
s,也可用于任何其他类型的滚动子项)。
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, canScrollVertically
is a View
method, so the ListView
can be safely replaced by a general View
or 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 对我来说是完美的。