SwipeRefreshLayout + WebView, когда позиция прокрутки находится наверху

Я пытаюсь использовать SwipeRefreshLayout с WebView.

Я столкнулся с проблемой, когда в середине страницы, когда пользователь прокручивается вниз, появляется нежелательное обновление.

Как сделать событие обновления только тогда, когда позиция прокрутки webview находится вверху. (т.е. он смотрит на верхнюю часть страницы)?

Ответ 1

Мне удалось решить эту проблему без необходимости продления. Взгляните на этот фрагмент (специфичный для фрагментов):

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 с пустым текстовым окном.

Ответ 2

Я думаю, что рекомендуемый способ сделать это - расширить 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();
    }
}

И в вашем 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;
    }
}

Ответ 3

Просто выполните Fragment или Activity с помощью ViewTreeObserver.OnScrollChangedListener, затем установите Listener как webview.getViewTreeObserver().addOnScrollChangedListener(this);

В onScrollChanged() метод делает это

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

Ответ 4

Вы можете решить эту проблему, расширив SwipeRefreshLayout с помощью специального SwipeRefreshLayout, который использует WebView и использует WebView для проверки положения прокрутки.

Примечание: Это будет работать для прокрутки всей страницы, но может не работать с вложенными свитками. Кроме того, если у вас есть горизонтальная прокрутка, вы также можете добавить логику, найденную в этом ответе: fooobar.com/questions/83146/...

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

Ответ 5

Я столкнулся с подобной проблемой, но ни один из ответов, приведенных здесь, не работает для меня. Итак, я получил решение от этого ответа.

Шаг 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, как это, -

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

Ответ 6

Ответ, предоставленный hiBrianLee, почти сработал у меня, но, как писал Джон Шелли, getScrollY всегда возвращал 0 в моем случае (я использовал ListView как вложенный ребенок прокрутки). Однако сработало то, что вместо этого следует использовать canScrollVertically (что является методом View, поэтому он доступен как для ListView, так и для WebView s, а также для любого другого типа прокручивающего дочернего элемента).

Мой класс макета выглядит следующим образом:

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 или любым другим специализированным классом вида.)

Ответ 7

Использовать SwipeRefreshLayout обычно, как и для других видов, но допускать вложенную прокрутку.

swipeRefreshLayout.setNestedScrollingEnabled(true);

Ответ 8

Я найду решение для него. Просто используйте CoordinatorLayout в качестве корневого макета и добавьте layout_behavior = "@string/appbar_scrolling_view_behavior" в ваш SwipeRefreshLayout. Идеально для меня.

Ответ 9

Я обнаружил, что отключить вложенную прокрутку на веб-просмотр (не сам SwipeRefreshLayout) отсортировал эту проблему для меня. Это не удастся сделать это во всех ситуациях, но было в моих.

webView.setNestedScrollingEnabled(false);