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