J'essaie d'utiliser SwipeRefreshLayout avec WebView.
Je suis confronté au problème suivant: au milieu de la page, lorsque l'utilisateur fait défiler l'écran vers le bas, un rafraîchissement indésirable se déclenche.
Comment faire en sorte que l'actualisation ne se produise que lorsque la position de défilement de la visualisation Web est en haut. (c'est-à-dire qu'il regarde la partie supérieure de la page)?
J'ai réussi à le résoudre sans avoir à étendre quoi que ce soit. Jetez un coup d'œil à cet extrait (spécifique à un fragment):
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();
}
Pour un contexte plus large, consultez ma réponse à Android - SwipeRefreshLayout avec textview vide .
Je pense que la méthode recommandée consiste à étendre la SwipeRefreshLayout
et à remplacer canChildScrollUp()
- https://developer.Android.com/reference/Android/support/v4/widget/SwipeRefreshLayout.html#canChildScrollUp ()
Voici comment cela se fait dans l'application 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
La CustomSwipeRefreshLayout
ressemblera probablement à:
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();
}
}
Et dans votre Activity
qui a le 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;
}
}
Implémentez simplement votre Fragment
ou Activity
avec ViewTreeObserver.OnScrollChangedListener
, puis définissez Listener comme webview.getViewTreeObserver().addOnScrollChangedListener(this);
Dans la méthode onScrollChanged()
faites comme ceci
@Override
public void onScrollChanged() {
if (webview.getScrollY() == 0) {
swipeLayout.setEnabled(true);
} else {
swipeLayout.setEnabled(false);
}
}
Vous pouvez résoudre ce problème en étendant SwipeRefreshLayout avec un SwipeRefreshLayout personnalisé qui intègre la vue Web et utilise cette vue pour vérifier la position de défilement.
Remarque: Cela fonctionnera pour faire défiler la page entière, mais cela peut ne pas fonctionner avec des parchemins imbriqués . De plus, si vous avez le défilement horizontal, vous pouvez également ajouter la logique trouvée dans cette réponse: 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);
}
}
Je faisais face à un problème similaire, mais aucune des réponses données ici ne fonctionne pour moi. Donc, j'ai une solution de ceci réponse.
Étape 1: Créer une classe 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);
}}
Étape 2: Dans le fichier xml, utilisez webview
comme ceci-
<com.yourpackagename.CustomWebView
Android:id="@+id/webview"
Android:layout_width="match_parent"
Android:layout_height="match_parent"/>
Étape 3: Dans votre MainActivity
, utilisez 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);
}
}
});
}
La réponse fournie par hiBrianLee presque a fonctionné pour moi, mais comme l’a écrit John Shelley, getScrollY
renvoyait toujours 0 dans mon cas (j’utilisais ListView
comme enfant à défilement imbriqué). Ce qui a immédiatement fonctionné, cependant, a été d'utiliser plutôt canScrollVertically
(qui est une méthode View
, donc disponible pour les ListView
s et les WebView
s, ainsi que pour tout autre type d'enfant de défilement).
Ma classe de mise en page se présente comme suit:
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();
}
}
(Comme indiqué, canScrollVertically
est une méthode View
. Par conséquent, la variable ListView
peut être remplacée en toute sécurité par une View
générale ou par toute autre classe d'affichage spécialisée.)
Je réponds à la même question mais en utilisant Kotlin. En activant swipeRefreshLayout
lorsque le scrollY de webView
obtient 0
:
Faites cette variable dans votre fragment ou activité:
private val onScrollChangedListener = ViewTreeObserver.OnScrollChangedListener{ swipeRefreshLayout.isEnabled = webView.scrollY == 0 }
Alors onViewCreated
:
swipeRefreshLayout.viewTreeObserver.addOnScrollChangedListener(onScrollChangedListener)
Alors onStop
:
swipeRefreshLayout.viewTreeObserver.removeOnScrollChangedListener(onScrollChangedListener)
À partir de là, tout fonctionnera bien. Mais si la page Web que vous utilisez a un en-tête fixe qui ne fait pas défiler scrollY
sera toujours égal à 0
Et cette solution ainsi que d'autres solutions dans cette page peuvent ne pas fonctionner.
Les versions les plus récentes de la bibliothèque de support ont la méthode SwipeRefreshLayout#setOnChildScrollUpCallback
qui vous permet d’éviter les sous-classes SwipeRefreshLayout
.
mBinding.swipeRefreshLayout.setOnChildScrollUpCallback((parent, child) ->
mBinding.webView.getScrollY() > 10);