Deaktivieren der Chrome-Pulldown-Funktion zum Aktualisieren von Android


135

Ich habe eine kleine HTML5-Webanwendung für mein Unternehmen erstellt.

Diese Anwendung zeigt eine Liste von Elementen an und alles funktioniert einwandfrei.

Die Anwendung wird hauptsächlich auf Android-Handys und Chrome als Browser verwendet. Außerdem wird die Site auf dem Startbildschirm gespeichert, sodass Android das Ganze als App verwaltet ( vermutlich mit einem WebView ).

Chrome Beta (und ich denke auch das Android System WebView) hat eine Funktion zum Herunterziehen zum Aktualisieren eingeführt ( siehe diesen Link zum Beispiel ).

Dies ist eine praktische Funktion, aber ich habe mich gefragt, ob sie mit einem Meta-Tag (oder Javascript-Material) deaktiviert werden kann, da die Aktualisierung vom Benutzer beim Navigieren in der Liste leicht ausgelöst werden kann und die gesamte App neu geladen wird.

Auch dies ist eine Funktion, die von der Anwendung nicht benötigt wird.

Ich weiß, dass diese Funktion nur in Chrome Beta verfügbar ist, aber ich habe das Gefühl, dass dies auch auf der stabilen App landet.

Danke dir!

Bearbeiten: Ich habe Chrome Beta deinstalliert und der Link zum Startbildschirm wird jetzt mit dem stabilen Chrome geöffnet. Die angehefteten Links beginnen also mit Chrome und nicht mit einer Webansicht.

Bearbeiten: Heute (19.03.2015) ist das Pulldown-to-Refresh auf das stabile Chrom gekommen.

Bearbeiten: von @Evyn Antwort Ich folge diesem Link und habe diesen Javascript / JQuery-Code, der funktioniert.

Wie @bcintegrity hervorhob, hoffe ich auf eine Lösung für das Site-Manifest (und / oder ein Meta-Tag) in der Zukunft.

Darüber hinaus sind Vorschläge für den obigen Code willkommen.


18
Ja, das ist wirklich scheiße. War in der Mitte der Form und zu weit nach oben gescrollt und es erfrischte und verlor alles. Dies ist eine verzögerte Standardfunktion. Ich klicke auf das Symbol Aktualisieren, wenn ich aktualisieren möchte.
Brock Hensley

12
Wäre schön, wenn diese Funktion in meinem Web-App-Manifest deaktiviert werden könnte. Leider enthält jede Seite meiner Web-App scrollbaren Inhalt, sodass das Navigieren ohne Aktualisierung fast unmöglich ist. Ich bin ein bisschen gekitzelt. : /
bcintegrity

Das sind gute Infos. Ich hasse Websites, die die Pull-to-Refresh-Funktion deaktivieren. Ich möchte eine Funktion entwickeln, mit der die Aktualisierung unabhängig vom Seiteninhalt funktioniert.
LS

5
Als Webentwickler ist die Pulldown-Aktualisierung nicht mit datengesteuerten Websites kompatibel, da die Anwendung neu geladen wird. Es macht es einem Benutzer unmöglich, zum Anfang einer Seite zu scrollen, ohne die gesamte Seite zu aktualisieren. Ich unterstütze Chrome zu 100% und hoffe, dass sie diese Anti-Funktion entfernen.
Bohnen

3
Ich habe mich mit dieser GC "Funktion" konfrontiert ... viele Webseiten, viele Formulare, ein unachtsames Herunterziehen mit dem Finger und Daten auf dieser Seite gehen verloren! Verzögerungsfunktion IMO. Es sollte standardmäßig ausgeschaltet sein, wer es braucht, dann lassen Sie es codieren. Ich habe mich tagelang gefragt, warum meine "Kunden" gelegentlich ihre Daten auf GC verloren haben ...
Ludus H

Antworten:


157

Die Standardaktion des Pull-to-Refresh-Effekts kann effektiv verhindert werden, indem Sie einen der folgenden Schritte ausführen:

  1. preventDefaulteinen Teil der Berührungssequenz, einschließlich einer der folgenden (in der Reihenfolge der störendsten bis am wenigsten störenden):
    • ein. Der gesamte Touch-Stream (nicht ideal).
    • b. Alle Top-Overscrolling-Touchmoves.
    • c. Der erste Top-Overscrolling-Touchmove.
    • d. Die erste Berührung des oberen Überrollens nur dann, wenn 1) der anfängliche Berührungsstart erfolgte, wenn der Versatz der Seite und des Bildlaufs Null war, und 2) die Berührung eine obere Überbewegung hervorrief.
  2. touch-action: noneGegebenenfalls Anwenden von " " auf berührungsbezogene Elemente, Deaktivieren von Standardaktionen (einschließlich Pull-to-Refresh) der Berührungssequenz.
  3. Anwenden von " overflow-y: hidden" auf das Körperelement, ggf. Verwenden eines div für scrollbaren Inhalt.
  4. Effekt lokal deaktivieren über chrome://flags/#disable-pull-to-refresh-effect).

Mehr sehen


12
Vielen Dank, dass Sie @Evyn. Ich kann nicht glauben, dass dies eine schnelle Lösung war! Ich habe das CSS für das body-Element auf overflow-y: hidden gesetzt.
Bcintegrity

Danke @Evyn, ich habe mich für die PreventDefault () -Methode entschieden (erster Punkt). Insbesondere fand ich den Quellcode des Links ( Links ), der sich in dem von Ihnen verknüpften Dokument befindet , interessant . Ich werde den Code am Ende meiner Frage einfügen.
Sebastiano

2
Wie wird "chrome: // flags (Disable-Pull-to-Refresh-Effekt)" programmgesteuert ausgeführt?
Jemand irgendwo

2
@SomeoneSomewhere soweit ich weiß, ist es nicht unmöglich. Chrome-Einstellungen können nur vom Benutzer festgelegt werden - es würde sonst ein Sicherheitsrisiko darstellen
Mike

1
Das Anwenden von "overflow-y: hidden" auf das body-Element mit einem div für scrollbaren Inhalt hat bei mir funktioniert.
Robin

102

Einfache Lösung für 2019+

Chrome 63 hat eine CSS-Eigenschaft hinzugefügt, um genau dies zu unterstützen. Lesen Sie diesen Leitfaden von Google durch , um eine gute Vorstellung davon zu erhalten, wie Sie damit umgehen können.

Hier ist ihre TL: DR

Mit der CSS-Eigenschaft "Overscroll-Verhalten" können Entwickler das Standard-Überlauf-Scroll-Verhalten des Browsers überschreiben, wenn sie den oberen / unteren Rand des Inhalts erreichen. Zu den Anwendungsfällen gehören das Deaktivieren der Pull-to-Refresh-Funktion auf Mobilgeräten, das Entfernen von Glüh- und Gummibandeffekten beim Überschreiben und das Verhindern, dass Seiteninhalte gescrollt werden, wenn sie sich unter einem Modal / Overlay befinden.

Damit es funktioniert, müssen Sie nur Folgendes in Ihrem CSS hinzufügen:

body {
  overscroll-behavior: contain;
}

Es wird derzeit auch nur von Chrome, Edge und Firefox unterstützt , aber ich bin sicher, Safari wird es hinzufügen, sobald sie mit den Servicemitarbeitern und der Zukunft der PWAs voll an Bord zu sein scheinen.


15
Dies ist die aktuellste Antwort
colxi

Hat jemand anderes bemerkt, dass dies das Erscheinen des Chrom-Banners "Add to Homescreen" verzögert?
Nathaniel Hill

2
musste es auf das HTML-Element anwenden, um es zu deaktivieren
Jakob Eriksson

1
Dies funktioniert nur für Android, Chrome auf IOs, um noch Glow-Effekt + native Pull zu
aktualisieren


15

Momentan können Sie diese Funktion nur über chrome: // flags / # disable-pull-to-refresh-effect deaktivieren - direkt von Ihrem Gerät aus öffnen.

Sie könnten versuchen, touchmoveEreignisse zu erfassen , aber die Chancen, ein akzeptables Ergebnis zu erzielen, sind sehr gering.


1
Vielen Dank, Kevin, für die Antwort. Ich konnte dies nicht als akzeptiert akzeptieren, da ich nach etwas suchte, das nicht von den Benutzern abhängig ist. Da diese Methode jedoch funktioniert, werde ich Ihre Antwort positiv bewerten, sobald ich genügend Ansehen erlangt habe.
Sebastiano

Schade, dass dies die beste Lösung zu sein scheint - was ist, wenn sich diese Flag-Einstellung in Zukunft ändert oder Sie Pull zum Aktualisieren auf anderen Websites verwenden möchten ... Überrascht, dass dies nicht programmgesteuert gesteuert werden kann. :(.
user1063287

1
Wenn der CEO von Google dies liest, entfernen Sie diese Funktion. Es scheint nicht, dass es einfach und umfassend deaktiviert werden kann, und meiner Meinung nach handelt es sich um eine Webanwendungsfunktion, die nicht alle Webanwendungen wünschen.
user1063287

8

Ich verwende MooTools und habe eine Klasse erstellt, um die Aktualisierung eines Zielelements zu deaktivieren. Der Kern davon ist jedoch (natives JS):

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

Alles, was wir hier tun, ist die y-Richtung der Berührungsbewegung zu finden. Wenn wir uns auf dem Bildschirm nach unten bewegen und die Zielrolle 0 ist, stoppen wir das Ereignis. Also keine Auffrischung.

Dies bedeutet, dass wir bei jedem "Zug" schießen, was teuer sein kann, aber die beste Lösung ist, die ich bisher gefunden habe ...


2
Es ist sicher, die Wiedergabe zu beenden, sobald der Benutzer einen Bildlauf nach unten durchführt, da der Pull zum Aktualisieren keine Chance hat, ausgelöst zu werden. Ebenso wird scrolltop > 0das Ereignis nicht ausgelöst. In meiner Implementierung binde ich das touchmoveEreignis touchstartnur dann an , wenn scrollTop <= 0. Ich binde die Bindung auf, sobald der Benutzer einen Bildlauf nach unten durchführt ( initialY >= e.touches[0].clientY). Wenn der Benutzer einen Bildlauf durchführt ( previousY < e.touches[0].clientY), rufe ich an preventDefault.
Nicolas Bouliane

7

Nach vielen Stunden des Versuchs funktioniert diese Lösung für mich

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

Es ist nicht erforderlich, jQuery dafür zu verwenden. Fügen Sie einfach die "touch-action: pan-down" zu Ihrer CSS-Codedatei hinzu.
Keegan Teetaert

1
Verwenden Sie dies einfach in Ihrem CSS:html{touch-action:pan-down}
csandreas1

5

AngularJS

Ich habe es mit dieser AngularJS-Direktive erfolgreich deaktiviert:

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

Es ist sicher, die Wiedergabe zu beenden, sobald der Benutzer einen Bildlauf nach unten durchführt, da das Ziehen zum Aktualisieren keine Chance hat, ausgelöst zu werden.

Ebenso wird scrolltop > 0das Ereignis nicht ausgelöst. In meiner Implementierung binde ich das touchmove-Ereignis nur dann an touchstart, wenn scrollTop <= 0. Ich binde die Bindung auf, sobald der Benutzer einen Bildlauf nach unten durchführt ( initialY >= e.touches[0].clientY). Wenn der Benutzer einen Bildlauf durchführt ( previousY < e.touches[0].clientY), rufe ich an preventDefault().

Dies erspart uns das unnötige Betrachten von Scroll-Ereignissen und blockiert gleichzeitig das Über-Scrollen.

jQuery

Wenn Sie jQuery verwenden, ist dies das nicht getestete Äquivalent. elementist ein jQuery-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");
        }
        previousY = e.touches[0].clientY;
    },
    unbindScrollEvent = function(e){
        element.off("touchmove");
    };
element.on("touchstart", bindScrollEvent);
element.on("touchend", unbindScrollEvent);

Dasselbe kann natürlich auch mit reinem JS erreicht werden.


Ich musste verwenden e.originalEvent.touches[0].clientY, um diese Arbeit zu machen. Ich habe immer noch Probleme mit der Logik, wann ein erneutes Laden verhindert werden soll. Im Moment scheint es zufällig zu verhindern, dass nach oben gescrollt wird ... Danke für den Hinweis in die richtige Richtung!
Thomas

Zu welchem ​​Element wird die Richtlinie hinzugefügt?
Fizzix

Die AngularJS-Richtlinie hat bei mir gut funktioniert. Wir verwenden Framework7 und Angular zusammen (würde es nicht vorschlagen) und etwas hat das korrekte Verhalten von scrollTop blockiert. Also musste ich ändern, wann der blockScroll zum Element hinzugefügt werden würde. Aber ich wollte mich nur bedanken!
Dustin Jensen

5

Einfaches Javascript

Ich habe mit Standard-Javascript implementiert. Einfach und leicht zu implementieren. Einfach einfügen und es funktioniert gut.

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

Dies funktionierte sehr gut für Chrome, verursachte jedoch einige Probleme beim Scrollen für mich unter Safari / iOS 9.2, wenn ein Div oben auf der Seite gescrollt wurde ( hier wiedergegeben ). Am Ende habe ich den body: {overflow-y:hidden}Trick von Evyn oben benutzt .
Sennett

hat nicht funktioniert Downvoting auf Chrom, aber funktioniert in firefox Beispiel embed.plnkr.co/rqbOVSOkKyhAgoHK2sEP öffnen in MOBILE ONLY
vijay

Der Link, den Sie eingefügt haben, funktionierte auch in Chrome auf meinem Android-Handy. Beim Ziehen konnte nicht aktualisiert werden. Welche Version von Android / iOS verwenden Sie zum Testen?
Sacky San

2
In Chrome 56 müssen Sie passiv: false festlegen, damit es funktioniert: document.addEventListener ('touchstart', touchstartHandler, {passiv: false}); document.addEventListener ('touchmove', touchmoveHandler, {passiv: false});
Anton Kuzmin

4

Die beste Lösung für reines CSS:

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

Siehe diese Demo: https://jsbin.com/pokusideha/quiet


Hast du das wirklich auf einem Handy mit Chrom getestet?
Gregor Voinov


3

Ich finde das Einstellen Ihres Körper- CSS- Überlaufs: Versteckt ist der einfachste Weg. Wenn Sie eine Bildlaufanwendungsseite haben möchten, können Sie einfach einen div-Container mit Bildlauffunktionen verwenden.


Scheint unmöglich, es mit einer Linie zu reparieren, funktioniert aber wie ein Zauber, vielen Dank!
Ignacio Ara

2

Beachten Sie, dass overflow-y nicht vererbt wird. Sie müssen es daher für ALLE Blockelemente festlegen.

Sie können dies mit jQuery einfach tun, indem Sie:

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

Unter den anderen Antworten hilft diese wirklich. Vielen Dank. Fügen Sie diese Zeile in CSS ein. Körper {Überlauf-y: versteckt; }
Sarin JS

2

Seit einigen Wochen habe ich festgestellt, dass die Javascript-Funktion, mit der ich die Chrome-Aktualisierungsaktion deaktiviert habe, nicht mehr funktioniert. Ich habe dies gemacht, um es zu lösen:

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

Reine js Lösung.

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

Was ich getan habe, war Folgendes zu den touchstartund touchend/ touchcancelEreignissen hinzuzufügen :

scrollTo(0, 1)

Da Chrom nicht scrollt, wenn es sich nicht in der Position scrollY befindet 0 wird verhindert, dass Chrome zum Aktualisieren zieht.

Wenn es immer noch nicht funktioniert, versuchen Sie dies auch beim Laden der Seite.


0

Ich habe das Pull-Down-to-Refresh-Problem damit gelöst:

html, body {
    width: 100%;
    height: 100%;
    overflow: hidden;
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.