Disabilita la funzione pull-down-to-refresh di Chrome di Android


135

Ho creato una piccola applicazione Web HTML5 per la mia azienda.

Questa applicazione visualizza un elenco di elementi e tutto funziona bene.

L'applicazione è utilizzata principalmente su telefoni Android e Chrome come browser. Inoltre, il sito viene salvato sulla schermata principale in modo che Android gestisca il tutto come un'app ( usando un WebView credo ).

Chrome Beta (e penso anche il sistema WebView di Android) ha introdotto una funzione "pull down to refresh" ( vedi questo link per esempio ).

Questa è una funzionalità utile, ma mi chiedevo se potesse essere disabilitato con alcuni meta tag (o roba javascript) perché l'aggiornamento può essere facilmente attivato dall'utente durante la navigazione dell'elenco e l'intera app viene ricaricata.

Anche questa è una funzione non necessaria per l'applicazione.

So che questa funzione è ancora disponibile solo nella versione beta di Chrome, ma ho la sensazione che anche questa stia atterrando sull'app stabile.

Grazie!

Modifica: ho disinstallato Chrome Beta e il collegamento aggiunto alla schermata principale ora si apre con Chrome stabile. Quindi i collegamenti aggiunti iniziano con Chrome e non con una visualizzazione Web.

Modifica: oggi (19-03-2015) il pull-down-to-refresh è arrivato al chrome stabile.

Modifica: dalla risposta di @Evyn seguo questo link e ho ottenuto questo codice javascript / jquery che funziona.

Come sottolineato da @bcintegrity, spero in futuro di trovare una soluzione manifest per il sito (e / o un meta-tag).

Inoltre sono benvenuti suggerimenti per il codice sopra.


18
Sì, questo fa davvero schifo. Era nel mezzo della forma e scorreva verso l'alto troppo lontano e rinfrescava e perdeva tutto. Questa è una funzionalità predefinita ritardata, faccio clic sull'icona Aggiorna se voglio aggiornare!
Brock Hensley,

12
Sarebbe bello se questa funzione potesse essere disabilitata nel mio manifest dell'app Web. Sfortunatamente, ogni pagina della mia app Web ha contenuti scorrevoli, rendendo quasi impossibile navigare senza aggiornare. Sono un po 'ticchettato. : /
bcintegrity

Questa è una buona informazione Odio i siti Web che disabilitano la funzione pull to refresh. Vorrei sviluppare una funzione per far funzionare l'aggiornamento a prescindere dal contenuto della pagina.
LS

5
Parlando come sviluppatore web, l'aggiornamento a discesa non è compatibile con i siti Web basati sui dati, in quanto ricarica l'applicazione. Ciò rende impossibile per un utente scorrere fino all'inizio di una pagina senza aggiornare l'intera pagina. Sono favorevole al 100% di Chrome, spero che rimuovano questa funzione.
Fagioli

3
Mi sono trovato di fronte a questa "caratteristica" GC ... molte pagine Web, molti moduli, un trascinamento trascurato con il dito e i dati in questa pagina sono persi! Funzione di ritardo IMO. Dovrebbe essere spento per impostazione predefinita, chi ne ha bisogno quindi lascialo codificare. A volte mi chiedevo perché i miei "clienti" ogni tanto perdessero i loro dati su GC ...
Ludus H,

Risposte:


157

L'azione predefinita dell'effetto pull-to-refresh può essere efficacemente impedita effettuando una delle seguenti operazioni:

  1. preventDefaultin una parte della sequenza tattile, incluso uno dei seguenti (nell'ordine dal più distruttivo al meno distruttivo):
    • un. L'intero flusso di tocco (non ideale).
    • b. Tutti i migliori movimenti touch-over.
    • c. Il primo touchmove supercrolling.
    • d. Il primo touchmove con overcolling superiore solo quando 1) il touchstart iniziale si è verificato quando l'offset di scorrimento pagina y era zero e 2) il touchmove avrebbe indotto un overcolling superiore.
  2. Applicando " touch-action: none" agli elementi con targeting per tocco, ove appropriato, disabilitando le azioni predefinite (incluso pull-to-refresh) della sequenza di tocchi.
  3. Applicando " overflow-y: hidden" all'elemento body, usando un div per il contenuto scorrevole, se necessario.
  4. Disabilitare l'effetto localmente tramite chrome://flags/#disable-pull-to-refresh-effect).

Vedi altro


12
Grazie @Evyn. Non posso credere che sia stata una soluzione rapida! Ho impostato il CSS per l'elemento body su overflow-y: hidden.
Integrità

Grazie @Evyn, ho deciso di utilizzare il metodo preventDefault () (primo punto). In particolare ho trovato interessante il codice sorgente del link ( link ) che si trova all'interno del documento che hai collegato. Metterò il codice alla fine della mia domanda.
Sebastiano

2
come si fa "chrome: // flags (disable-pull-to-refresh-effect)" programmaticamente?
Someone Somewhere,

2
@SomeoneSomewhere per quanto ne so, non è impossibile. le impostazioni di Chrome possono essere configurate dall'utente - ciò costituirebbe un rischio per la sicurezza altrimenti
Mike

1
Applicando "overflow-y: hidden" sull'elemento body, usando un div per i contenuti scorrevoli ha funzionato per me.
Robin,

103

Soluzione semplice per il 2019+

Chrome 63 ha aggiunto una proprietà CSS per dare una mano con questo. Leggi questa guida di Google per avere una buona idea di come gestirla.

Ecco il loro TL: DR

La proprietà CSS overscroll-behavior consente agli sviluppatori di ignorare il comportamento di scorrimento di overflow predefinito del browser quando raggiungono la parte superiore / inferiore del contenuto. I casi d'uso includono la disabilitazione della funzione pull-to-refresh sui dispositivi mobili, la rimozione di effetti di bagliore e di scorrimento della gomma eccessivi e la prevenzione dello scorrimento del contenuto della pagina quando si trova sotto un modale / overlay.

Per farlo funzionare, tutto ciò che devi aggiungere è questo nel tuo CSS:

body {
  overscroll-behavior: contain;
}

È anche supportato solo da Chrome, Edge e Firefox per ora, ma sono sicuro che Safari lo aggiungerà presto poiché sembrano essere pienamente integrati con gli operatori del servizio e il futuro dei PWA.


16
questa è la risposta più aggiornata
colxi

Qualcun altro ha notato questo ritardare la comparsa del banner cromato "Aggiungi a Homescreen"?
Nathaniel Hill

2
ha dovuto applicarlo all'elemento html per disabilitarlo
Jakob Eriksson

1
Questo funziona solo per Android, Chrome su IO ancora per mostrare l'effetto bagliori + pull nativo per aggiornare
Fky


15

Al momento puoi disabilitare questa funzione solo tramite chrome: // flags / # disable-pull-to-refresh-effect - apri direttamente dal tuo dispositivo.

Potresti provare a catturare touchmoveeventi, ma le possibilità sono molto scarse per ottenere un risultato accettabile.


1
Grazie Kevin per la risposta. Non potevo accettarlo come accettato perché stavo cercando qualcosa che non dipendesse dagli utenti. Tuttavia, questo metodo funziona, quindi voterò la tua risposta man mano che mi guadagnerò abbastanza reputazione.
Sebastiano,

È un peccato che questa sia la soluzione migliore - cosa succederebbe se quell'impostazione della bandiera cambiasse in futuro, o se vuoi essere in grado di usare pull per aggiornare su altri siti ... Sorpreso che non possa essere controllato a livello di programmazione. :(.
user1063287

1
Se il CEO di Google sta leggendo questo, rimuovi questa funzione. Non sembra che possa essere disabilitato facilmente e in modo completo, e secondo me è una "caratteristica" dell'applicazione web che non tutte le applicazioni web desiderano.
user1063287

8

Uso MooTools e ho creato una classe per disabilitare l'aggiornamento su un elemento target, ma il punto cruciale è (JS nativo):

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

Tutto ciò che facciamo qui è trovare la direzione y del touchmove e se ci stiamo spostando verso il basso dello schermo e lo scorrimento target è 0, interrompiamo l'evento. Pertanto, nessun aggiornamento.

Ciò significa che stiamo sparando su ogni "mossa", che può essere costosa, ma è la migliore soluzione che ho trovato finora ...


2
È sicuro interrompere la visione non appena l'utente scorre verso il basso, poiché il pull per aggiornare non ha possibilità di essere attivato. Allo stesso modo, se scrolltop > 0l'evento non verrà attivato. Nella mia implementazione, vincolo l' touchmoveevento touchstart, solo se scrollTop <= 0. Lo separo non appena l'utente scorre verso il basso ( initialY >= e.touches[0].clientY). Se l'utente scorre verso l'alto ( previousY < e.touches[0].clientY), allora chiamo preventDefault.
Nicolas Bouliane,

7

Dopo molte ore di tentativi, questa soluzione funziona per me

$("html").css({
    "touch-action": "pan-down"
});

Non è necessario utilizzare jQuery per questo. Basta aggiungere "touch-action: pan-down" al file di codice CSS.
Keegan Teetaert,

1
basta usare questo nel tuo CSS:html{touch-action:pan-down}
csandreas1

5

AngularJS

L'ho disabilitato con successo con questa direttiva 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);
        }
    };
});

È sicuro interrompere la visione non appena l'utente scorre verso il basso, poiché il pull per aggiornare non ha possibilità di essere attivato.

Allo stesso modo, se scrolltop > 0l'evento non verrà attivato. Nella mia implementazione, associo l'evento touchmove al touchstart, solo se scrollTop <= 0. Lo separo non appena l'utente scorre verso il basso ( initialY >= e.touches[0].clientY). Se l'utente scorre verso l'alto ( previousY < e.touches[0].clientY), allora chiamo preventDefault().

Questo ci evita di guardare eventi di scorrimento inutilmente, ma blocca l'eccessivo controllo.

jQuery

Se si utilizza jQuery, questo è l' equivalente non testato . elementè un elemento 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);

Naturalmente, lo stesso può essere ottenuto anche con JS puro.


Ho dovuto usare e.originalEvent.touches[0].clientYper farlo funzionare. Ancora alle prese con la logica quando impedire il ricaricamento. In questo momento sembra impedire in modo casuale lo scorrimento verso l'alto ... Metti grazie per il suggerimento nella giusta direzione!
Thomas,

A quale elemento è aggiunta la direttiva?
Fizzix,

La direttiva AngularJS ha funzionato bene per me. Stiamo usando Framework7 e Angular insieme (non lo suggerirei) e qualcosa stava bloccando il comportamento corretto di scrollTop. Quindi ho dovuto modificare quando il blockScroll sarebbe stato aggiunto all'elemento. Ma volevo solo dire grazie!
Dustin Jensen,

5

Javascript semplice

Ho implementato usando javascript standard. Semplice e facile da implementare. Basta incollare e funziona bene.

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

Questo ha funzionato molto bene per Chrome, ma ha causato alcuni problemi con lo scorrimento verso l'alto su Safari / iOS 9.2 durante lo scorrimento di un div nella parte superiore della pagina (riprodotto qui ). Ho finito per usare il body: {overflow-y:hidden}trucco di Evyn sopra .
Sennett,

il downvoting non funziona su Chrome, ma funziona nell'esempio di Firefox, embed.plnkr.co/rqbOVSOkKyhAgoHK2sEP aperto SOLO
IN

il link che hai incollato ha funzionato anche su Chrome sul mio cellulare Android. non ha permesso di aggiornare al pull. quale versione di Android / iOS stai usando per testare?
Sacky San

2
Da Chrome 56 devi impostare passivo: false per farlo funzionare: document.addEventListener ('touchstart', touchstartHandler, {passive: false}); document.addEventListener ('touchmove', touchmoveHandler, {passive: false});
Anton Kuzmin,

4

La migliore soluzione su CSS puro:

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

Guarda questa demo: https://jsbin.com/pokusideha/quiet


lo hai davvero provato su un dispositivo mobile usando Chrome?
Gregor Voinov,


3

Trovo che l'impostazione del tuo corpo CSS trabocca-y: nascosto è il modo più semplice. Se volevi avere una pagina di applicazione a scorrimento, puoi semplicemente usare un contenitore div con funzionalità di scorrimento.


Sembra impossibile ripararlo con una linea ma funziona come un incantesimo, grazie mille!
Ignacio Ara

2

Si noti che overflow-y non è ereditato, quindi è necessario impostarlo su TUTTI gli elementi del blocco.

Puoi farlo con jQuery semplicemente:

        $(document.body).css('overflow-y', 'hidden'); 
        $('*').filter(function(index) {
            return $(this).css('display') == 'block';
        }).css('overflow-y', 'hidden');

Tra le altre risposte, questa aiuta davvero. Grazie. Aggiungi questa riga in CSS. body {overflow-y: nascosto; }
Sarin JS,

2

Da un paio di settimane ho scoperto che la funzione javascript che ho usato per disabilitare l'azione di aggiornamento di Chrome non funzionerà più. Ho fatto questo per risolverlo:

$(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>


1

Soluzione js pura.

// 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

Quello che ho fatto è stato aggiungere seguenti a touchstarte touchend/ touchcanceleventi:

scrollTo(0, 1)

Poiché Chrome non scorre se non è in posizione di scorrimentoY, 0ciò impedirà a Chrome di eseguire pull per aggiornare.

Se il problema persiste, provare a farlo anche al caricamento della pagina.


0

Ho risolto il problema del pull-down-to-refresh con questo:

html, body {
    width: 100%;
    height: 100%;
    overflow: hidden;
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.