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

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

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

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

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

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

В onScrollChanged() сделать это

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

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

Примечание. Это будет работать для прокрутки всей страницы, но может не работать с вложенными прокрутками. Кроме того, если у вас есть горизонтальная прокрутка, вы также можете добавить логику, найденную в этом ответе: 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

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

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

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

 swipeRefreshLayout.setNestedScrollingEnabled(true);