Désactivation de chrome Android déroulant à rafraîchir fonction

J'ai créé une petite application web HTML5 pour mon entreprise.

Cette application affiche une liste d'éléments et tout fonctionne bien.

L'application est principalement utilisée sur les téléphones android et Chrome comme navigateur. En outre, le site est enregistré sur l'écran d'accueil afin que Android gère le tout comme une application ( en utilisant un WebView je suppose).

Chrome Beta (et je pense aussi que le système Android WebView) {[7] } a introduit une fonctionnalité" pull down to refresh " ( voir ceci lien par exemple).

C'est une fonctionnalité pratique mais je me demandais si elle pouvait être désactivée avec une balise meta (ou des trucs javascript) car l'actualisation peut être facilement déclenchée par l'utilisateur tout en naviguant dans la liste et l'application entière est rechargée.

Il s'agit également d'une fonctionnalité non nécessaire à l'application.

je sais que cette fonctionnalité est toujours disponible uniquement dans Chrome beta, mais j'ai la sensation que cela atterrit sur l'application stable, aussi.

Merci vous!

Edit: J'ai désinstallé Chrome Beta et le lien épinglé à l'écran d'accueil s'ouvre maintenant avec le chrome stable. Donc, les liens épinglés commencent par Chrome et non par un webview.

Edit: aujourd'hui (2015-03-19) le pull-down-to-refresh est venu à l'écurie chrome.

Edit: de la réponse @ Evyn je suis ce lien et j'ai ce code javascript / jquery qui fonctionne.

var lastTouchY = 0;
var preventPullToRefresh = false;

$('body').on('touchstart', function (e) {
    if (e.originalEvent.touches.length != 1) { return; }
    lastTouchY = e.originalEvent.touches[0].clientY;
    preventPullToRefresh = window.pageYOffset == 0;
});

$('body').on('touchmove', function (e) {
    var touchY = e.originalEvent.touches[0].clientY;
    var touchYDelta = touchY - lastTouchY;
    lastTouchY = touchY;
    if (preventPullToRefresh) {
        // To suppress pull-to-refresh it is sufficient to preventDefault the first overscrolling touchmove.
        preventPullToRefresh = false;
        if (touchYDelta > 0) {
            e.preventDefault();
            return;
        }
    }
});

Comme @ bcintegrity l'a souligné, j'espère une solution de manifeste de site (et / ou une méta-balise) dans le futur.

De plus, les suggestions pour le code ci-dessus sont les bienvenues.

105
demandé sur Sebastiano 2015-03-12 14:10:53

13 réponses

L'action par défaut de l'effet pull-to-refresh peut être efficacement évitée en effectuant l'une des opérations suivantes :

  1. preventDefault ' ing une partie de la séquence tactile, y compris l'un des éléments suivants (dans l'ordre du plus perturbateur au moins perturbateur):
    • a. le flux tactile entier (pas idéal).
    • B. tous les touchmoves supérieurs overscrolling.
    • C. le premier touchmove supérieur overscrolling.
    • d. le premier touchmove supérieur de overscrolling seulement quand 1) Le le touchstart initial s'est produit lorsque le décalage de défilement de la page y était nul et 2) le touchmove induirait un overscroll supérieur.
  2. Appliquer "touch-action: none " aux éléments ciblés par le toucher, le cas échéant, désactiver les actions par défaut (y compris le pull-to-refresh) de la séquence tactile.
  3. Appliquer "overflow-y: hidden " à l'élément body, en utilisant un div pour le contenu défilant si nécessaire.
  4. désactiver l'effet localement via chrome://flags/#disable-pull-to-refresh-effect).

Voir plus d'

127
répondu Evyn 2018-08-28 17:05:57

Solution Simple pour 2018 +

Chrome 63 (publié 5 décembre 2017) a ajouté une propriété css pour aider avec exactement cela. Lisez ce guide par Google pour obtenir une bonne idée de la façon dont vous pouvez le manipuler.

Voici leur TL: DR

La propriété CSS overscroll-behavior permet aux développeurs de comportement de défilement de débordement par défaut du navigateur lorsque vous atteignez le haut de page/bas de contenu. Les cas d'utilisation incluent la désactivation du pull-to-refresh caractéristique sur mobile, enlever overscroll lueur et rubberbanding effets, et empêcher le contenu de la page de défiler quand il est sous un modal / superposition.

Pour le faire fonctionner, tout ce que vous devez ajouter est ceci:

body {
  overscroll-behavior: contain;
}

Il est également seulement pris en charge par Chrome, Edge et Firefox pour l'instant, mais je suis sûr que Safari l'ajoutera bientôt car ils semblent être entièrement à bord avec les travailleurs de service et l'avenir de PWA.

33
répondu Matthew Mullin 2018-09-27 13:39:06

Pour le moment, vous ne pouvez désactiver cette fonctionnalité que via chrome://flags/#disable-pull-to-refresh-effect - Ouvrir directement depuis votre appareil.

Vous pouvez essayer d'attraper les événements touchmove, mais les chances sont très minces d'obtenir un résultat acceptable.

14
répondu Kevin Busse 2015-03-20 16:31:42

J'utilise MooTools, et j'ai créé une classe pour désactiver l'actualisation sur un élément ciblé, mais le nœud est (js natif):

var target = window; // this can be any scrollable element
var last_y = 0;
target.addEventListener('touchmove', function(e){
    var scrolly = target.pageYOffset || target.scrollTop || 0;
    var direction = e.changedTouches[0].pageY > last_y ? 1 : -1;
    if(direction>0 && scrolly===0){
        e.preventDefault();
    }
    last_y = e.changedTouches[0].pageY;
});

Tout ce que nous faisons ici est de trouver la direction y du touchmove, et si nous descendons l'écran et que le défilement cible est 0, nous arrêtons l'événement. Ainsi, pas de rafraîchissement.

Cela signifie que nous progressons chaque "mouvement", qui peut être coûteux, mais c'est la meilleure solution que j'ai trouvé jusqu'à présent ...

7
répondu Eclectic 2015-03-27 14:16:27

AngularJS

Je l'ai désactivé avec succès avec cette directive AngularJS:

//Prevents "pull to reload" behaviour in Chrome. Assign to child scrollable elements.
angular.module('hereApp.directive').directive('noPullToReload', function() {
    'use strict';

    return {
        link: function(scope, element) {
            var initialY = null,
                previousY = null,
                bindScrollEvent = function(e){
                    previousY = initialY = e.touches[0].clientY;

                    // Pull to reload won't be activated if the element is not initially at scrollTop === 0
                    if(element[0].scrollTop <= 0){
                        element.on("touchmove", blockScroll);
                    }
                },
                blockScroll = function(e){
                    if(previousY && previousY < e.touches[0].clientY){ //Scrolling up
                        e.preventDefault();
                    }
                    else if(initialY >= e.touches[0].clientY){ //Scrolling down
                        //As soon as you scroll down, there is no risk of pulling to reload
                        element.off("touchmove", blockScroll);
                    }
                    previousY = e.touches[0].clientY;
                },
                unbindScrollEvent = function(e){
                    element.off("touchmove", blockScroll);
                };
            element.on("touchstart", bindScrollEvent);
            element.on("touchend", unbindScrollEvent);
        }
    };
});

Il est sûr d'arrêter de regarder dès que l'utilisateur fait défiler vers le bas, car la traction pour rafraîchir n'a aucune chance d'être déclenchée.

De Même, si scrolltop > 0, l'événement ne sera pas déclenché. Dans mon implémentation, je lie l'événement touchmove sur touchstart, seulement si scrollTop <= 0. Je le détache dès que l'utilisateur défile vers le bas (initialY >= e.touches[0].clientY). Si l'utilisateur fait défiler (previousY < e.touches[0].clientY), alors j'appelle preventDefault().

Ce nous évite de regarder les événements de défilement inutilement, mais bloque le défilement.

JQuery

Si vous utilisez jQuery, c'est le non testé équivalent. element est un élément jQuery:

var initialY = null,
    previousY = null,
    bindScrollEvent = function(e){
        previousY = initialY = e.touches[0].clientY;

        // Pull to reload won't be activated if the element is not initially at scrollTop === 0
        if(element[0].scrollTop <= 0){
            element.on("touchmove", blockScroll);
        }
    },
    blockScroll = function(e){
        if(previousY && previousY < e.touches[0].clientY){ //Scrolling up
            e.preventDefault();
        }
        else if(initialY >= e.touches[0].clientY){ //Scrolling down
            //As soon as you scroll down, there is no risk of pulling to reload
            element.off("touchmove");
        }
        previousY = e.touches[0].clientY;
    },
    unbindScrollEvent = function(e){
        element.off("touchmove");
    };
element.on("touchstart", bindScrollEvent);
element.on("touchend", unbindScrollEvent);

Naturellement, la même chose peut également être obtenue avec JS pur.

4
répondu Nicolas Bouliane 2015-08-07 12:21:54

Javascript Simple

J'ai implémenté en utilisant javascript standard. Simple et facile à mettre en œuvre. Il suffit de coller et cela fonctionne très bien.

<script type="text/javascript">         //<![CDATA[
     window.addEventListener('load', function() {
          var maybePreventPullToRefresh = false;
          var lastTouchY = 0;
          var touchstartHandler = function(e) {
            if (e.touches.length != 1) return;
            lastTouchY = e.touches[0].clientY;
            // Pull-to-refresh will only trigger if the scroll begins when the
            // document's Y offset is zero.
            maybePreventPullToRefresh =
                window.pageYOffset == 0;
          }

          var touchmoveHandler = function(e) {
            var touchY = e.touches[0].clientY;
            var touchYDelta = touchY - lastTouchY;
            lastTouchY = touchY;

            if (maybePreventPullToRefresh) {
              // To suppress pull-to-refresh it is sufficient to preventDefault the
              // first overscrolling touchmove.
              maybePreventPullToRefresh = false;
              if (touchYDelta > 0) {
                e.preventDefault();
                return;
              }
            }
          }

          document.addEventListener('touchstart', touchstartHandler, false);
          document.addEventListener('touchmove', touchmoveHandler, false);      });
            //]]>    </script>
4
répondu Sacky San 2016-02-04 23:19:43

La meilleure solution sur CSS pur:

body {
    width: 100%;
    height: 100%;
    display: block;
    position: absolute;
    top: -1px;
    z-index: 1;
    margin: 0;
    padding: 0;
    overflow-y: hidden;
}
#pseudobody {
    width:100%;
    height: 100%;
    position: absolute;
    top:0;
    z-index: 2;
    margin: 0;
    padding:0;
    overflow-y: auto;
}

Voir cette démo: https://jsbin.com/pokusideha/quiet

4
répondu Eugene Fox 2017-02-25 18:11:33

Après de nombreuses heures d'essai, Cette solution fonctionne pour moi

$("html").css({
    "touch-action": "pan-down"
});
4
répondu José Loguercio 2017-03-31 08:15:00

Je trouve que définir votre body CSS overflow-y:hidden est le moyen le plus simple. Si vous vouliez avoir une page d'application de défilement, vous pouvez simplement utiliser un conteneur div avec des fonctionnalités de défilement.

3
répondu Keegan Teetaert 2017-09-01 04:33:48

Depuis quelques semaines, j'ai découvert que la fonction javascript que j'ai utilisée pour désactiver L'action d'actualisation Chrome ne fonctionnera plus. J'ai fait cela pour le résoudre:

$(window).scroll(function() {
   if ($(document).scrollTop() >= 1) {
      $("html").css({
         "touch-action": "auto"}
      );
   } else {
      $("html").css({
         "touch-action": "pan-down"
      });
   }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
2
répondu Wobbo 2017-03-01 15:04:06

Notez que overflow-y n'est pas hérité, vous devez donc le définir sur tous les éléments de bloc.

Vous pouvez le faire avec jQuery simplement:

        $(document.body).css('overflow-y', 'hidden'); 
        $('*').filter(function(index) {
            return $(this).css('display') == 'block';
        }).css('overflow-y', 'hidden');
1
répondu kofifus 2016-05-04 11:44:19

Ce que j'ai fait était d'ajouter la suite au touchstart et touchend/touchcancel événements:

scrollTo(0, 1)

Comme chrome ne défile pas s'il n'est pas en position de défilement 0, Cela empêchera chrome de faire pull pour actualiser.

Si cela ne fonctionne toujours pas, essayez également de le faire lorsque la page se charge.

0
répondu xdevs23 2017-10-20 09:39:15

Solution js Pure.

// Prevent pull refresh chrome
    var lastTouchY = 0;
    var preventPullToRefresh = false;
    window.document.body.addEventListener("touchstart", function(e){
        if (e.touches.length != 1) { return; }
        lastTouchY = e.touches[0].clientY;
        preventPullToRefresh = window.pageYOffset == 0;
    }, false);

    window.document.body.addEventListener("touchmove", function(e){

        var touchY = e.touches[0].clientY;
        var touchYDelta = touchY - lastTouchY;
        lastTouchY = touchY;
        if (preventPullToRefresh) {
            // To suppress pull-to-refresh it is sufficient to preventDefault the first overscrolling touchmove.
            preventPullToRefresh = false;
            if (touchYDelta > 0) {
                e.preventDefault();
                return;
            }
        }

    }, false);
0
répondu user1503606 2017-10-25 12:21:26