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.

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

Evyn
quelle
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.

Matthew Mullin
quelle
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
developer.google.com/web/updates/2017/11/overscroll-behavior Dieser Link kann auch besser erklären
arung86
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.

Kevin Sandow
quelle
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 ...

Eklektisch
quelle
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"
});
José Loguercio
quelle
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.

Nicolas Bouliane
quelle
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>
Sacky San
quelle
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

Eugene Fox
quelle
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.

Keegan Teetaert
quelle
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');
Kofifus
quelle
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>

Wobbo
quelle
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);
user1503606
quelle
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.

xdevs23
quelle
0

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

html, body {
    width: 100%;
    height: 100%;
    overflow: hidden;
}
Paul Iştoan
quelle