android webview swiperefreshlayout

android - SwipeRefreshLayout+WebView cuando la posición de desplazamiento está en la parte superior



(11)

Estoy tratando de usar SwipeRefreshLayout con WebView.

Estoy enfrentando el problema donde, en medio de la página, cuando el usuario se desplaza hacia abajo, entra en acción una actualización no deseada

¿Cómo puedo hacer que el evento de actualización solo ocurra cuando la posición de desplazamiento de webview está en la parte superior? (es decir, está mirando la parte superior de la página)?


Creo que la forma recomendada de hacer esto es extender SwipeRefreshLayout y anular canChildScrollUp() - https://developer.android.com/reference/android/support/v4/widget/SwipeRefreshLayout.html#canChildScrollUp()

Así es como se hace en la aplicación 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

El CustomSwipeRefreshLayout probablemente se verá como:

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

Y en tu Activity que tiene el 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; } }


Descubrí que el problema estaba deshabilitado en la vista web (no en SwipeRefreshLayout). No será posible hacer esto en todas las situaciones, pero fue en la mía.

webView.setNestedScrollingEnabled(false);


Encuentro una solución para ello. Simplemente use CoordinatorLayout como diseño raíz y agregue layout_behavior = "@ string / appbar_scrolling_view_behavior" a su SwipeRefreshLayout. Es perfecto para mí.


Estoy respondiendo la misma pregunta pero usando Kotlin. Al habilitar swipeRefreshLayout cuando el scrollY de webView obtiene 0 :

Haz esta variable en tu fragmento o actividad:

private val onScrollChangedListener = ViewTreeObserver.OnScrollChangedListener{ swipeRefreshLayout.isEnabled = webView.scrollY == 0 }

Entonces onViewCreated :

swipeRefreshLayout.viewTreeObserver.addOnScrollChangedListener(onScrollChangedListener)

Entonces onStop :

swipeRefreshLayout.viewTreeObserver.removeOnScrollChangedListener(onScrollChangedListener)

Desde aquí todo funcionará bien. Pero si la página web que está utilizando tiene un encabezado fijo que no se desplaza, scrollY siempre será igual a 0 . Y esta solución junto con otra solución en esta página puede no funcionar.


He logrado resolverlo sin tener que extender nada. Echa un vistazo a este fragmento (específico del fragmento):

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

Para un contexto más amplio, eche un vistazo a mi respuesta a Android - SwipeRefreshLayout con vista de texto vacía .


La respuesta proporcionada por hiBrianLee casi me funcionó, pero como escribió John Shelley, getScrollY siempre devolvió 0 en mi caso (usé un ListView como el niño de desplazamiento anidado). Sin embargo, lo que funcionó de inmediato fue utilizar canScrollVertically (que es un método de View , por lo que está disponible tanto para ListView s como para WebView s, y también para cualquier otro tipo de niño con desplazamiento).

Mi clase de diseño se ve como sigue:

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

(Como se mencionó, canScrollVertically es un método de View , por lo que ListView puede ser reemplazado de forma segura por una View general o cualquier otra clase de vista especializada).


Las versiones más recientes de la biblioteca de soporte tienen SwipeRefreshLayout#setOnChildScrollUpCallback método SwipeRefreshLayout#setOnChildScrollUpCallback que le permite evitar la subclasificación de SwipeRefreshLayout .

mBinding.swipeRefreshLayout.setOnChildScrollUpCallback((parent, child) -> mBinding.webView.getScrollY() > 10);


Me enfrentaba a un problema similar, pero ninguna de las respuestas dadas aquí funciona para mí Entonces, tengo una solución de this respuesta.

Paso 1 : Crear clase 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); }}

Paso 2 : en el archivo xml use webview como este-

<com.yourpackagename.CustomWebView android:id="@+id/webview" android:layout_width="match_parent" android:layout_height="match_parent"/>

Paso 3 : en su MainActivity use 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); } } }); }


Puede resolver esto extendiendo SwipeRefreshLayout con un SwipeRefreshLayout personalizado que toma el WebView y use el WebView para verificar la posición de desplazamiento.

Nota: Esto funcionará para desplazar toda la página, pero puede que no funcione con los desplazamientos anidados. Además, si tiene desplazamiento horizontal, es posible que también desee agregar la lógica que se encuentra en esta respuesta: https://.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); } }


Simplemente implemente su Fragment o Activity con ViewTreeObserver.OnScrollChangedListener luego configure el Oyente como webview.getViewTreeObserver().addOnScrollChangedListener(this);

En el método onScrollChanged() haz esto

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


Use SwipeRefreshLayout normalmente como lo hace con otras vistas, pero habilite el desplazamiento anidado.

swipeRefreshLayout.setNestedScrollingEnabled(true);