禁用Android的Chrome下拉至刷新功能


135

我为公司创建了一个小型HTML5 Web应用程序。

此应用程序显示项目列表,一切正常。

该应用程序主要用于Android手机和Chrome浏览器。此外,该网站保存在主屏幕上,因此Android可以将整个内容作为应用程序进行管理(我猜是使用WebView)。

Chrome Beta(我也认为Android System WebView)已经引入了“下拉刷新”功能(例如,请参阅此链接)。

这是一个方便的功能,但是我想知道是否可以使用某些meta标记(或javascript东西)将其禁用,因为用户可以在浏览列表时轻松触发刷新,然后重新加载整个应用。

这也是应用程序不需要的功能。

我知道此功能仅在Chrome beta版中仍然可用,但是我有一种感觉,那就是该功能也将登陆稳定的应用程序。

谢谢!

编辑:我已经卸载了Chrome Beta,并且固定到主屏幕的链接现在随稳定的Chrome一起打开。因此,固定链接以Chrome开头,而不是以webview开头。

编辑:今天(2015-03-19)下拉菜单已刷新到稳定的Chrome。

编辑:从@Evyn答案我点击此链接并获得了有效的javascript / jquery代码。

正如@bcintegrity指出的那样,我希望将来有一个站点清单解决方案(和/或元标记)。

此外,欢迎提供上述代码的建议。


18
是的,这真的很烂。处于中间状态,滚动到顶部太远,它刷新并丢失了所有内容。这是默认的延迟功能,如果要刷新,请单击“刷新”图标!
布罗克·亨斯利

12
如果可以在我的网络应用清单中禁用此功能,那就太好了。不幸的是,我的Web应用程序上的每个页面都具有可滚动的内容,因此如果不刷新就几乎无法导航。我有点打勾。:/
bcintegrity 2015年

这是好信息。我讨厌禁用拉动刷新功能的网站。我想开发一种功能,使刷新工作无论页面内容如何。
LS

5
作为网络开发人员,下拉刷新与数据驱动的网站不兼容,因为它会重新加载应用程序。这使得用户无法滚动到页面顶部而不刷新整个页面。我100%支持Chrome,希望他们删除此反功能。
Beans

3
我面对着这个GC的“功能” ...大量的网页,多种形式,一个粗心的下拉菜单以及此页面上的数据都丢失了!延迟功能IMO。默认情况下它应该关闭,需要它的人然后让它编码。我想知道为什么我的“客户”偶尔会丢失他们在GC上的数据...
Ludus H

Answers:


157

通过执行以下任一操作,可以有效地防止“上拉刷新”效果的默认操作:

  1. preventDefault触摸顺序的某些部分,包括以下任何一项(从破坏性最大到破坏性最小的顺序):
    • 一个。整个触摸流(不理想)。
    • b。所有顶部滚动动作。
    • C。第一个超滚动触摸移动。
    • d。仅在以下情况下才进行第一次顶部超滚动触摸移动:1)当页面y滚动偏移为零时发生了初始触摸启动,以及2)触摸会引起顶部超滚动。
  2. touch-action: none在适当的情况下,将“ ”应用于以触摸为目标的元素,以禁用触摸序列的默认操作(包括“拉动刷新”)。
  3. 将“ overflow-y: hidden”应用于body元素,必要时使用div表示可滚动内容。
  4. 通过chrome://flags/#disable-pull-to-refresh-effect)在本地禁用效果。

看更多


12
谢谢@Evyn。我不敢相信这是一个快速解决方案!我将body元素的CSS设置为overflow-y:hidden。
bcintegrity,2015年

感谢@Evyn,我决定使用preventDefault()方法(第一点)。特别是,我发现您链接的文档内部的链接(link)的源代码很有趣。我将代码放在问题的末尾。
塞巴斯蒂

2
如何以编程方式完成“ chrome:// flags(禁用拉动刷新效果)”?
某处某人

2
据我所知,@ SomeoneSomewhere并非不可能。Chrome浏览器设置只能由用户设置-否则它将带来安全风险
麦克

1
将“ overflow-y:hidden”应用于body元素,使用div作为可滚动内容对我有用。
罗宾(Robin)

103

2019+的简单解决方案

Chrome 63添加了css属性来帮助您解决此问题。仔细阅读Google的本指南,以了解如何使用它。

这是他们的TL:DR

CSS overscroll-behavior属性允许开发人员在到达内容的顶部/底部时覆盖浏览器的默认溢出滚动行为。用例包括禁用移动设备上的“推入刷新”功能,消除过度滚动的辉光和橡皮筋效果,以及防止页面内容位于模式/重叠下方时滚动页面。

为了使其正常工作,您只需在CSS中添加以下内容:

body {
  overscroll-behavior: contain;
}

目前,Chrome,Edge和Firefox 也仅支持该功能,但是我敢肯定Safari会尽快添加它,因为它们似乎已经完全融入了服务工作者和PWA的未来。


16
这是最新的答案
colxi

其他人是否注意到这延迟了“添加到主屏幕” chrome横幅的显示?
纳撒尼尔·希尔

2
必须将其应用于html元素才能禁用它
Jakob Eriksson

1
此功能仅适用于Android,IO上的Chrome仍显示发光效果+原生拉动刷新
Fky


15

目前,您只能通过chrome:// flags /#disable-pull-to-refresh-effect禁用此功能-直接从设备打开。

您可以尝试捕捉touchmove事件,但是获得可接受结果的机会很小。


1
谢谢凯文(Kevin)的回答。我不能接受这一点,因为我正在寻找不依赖用户的东西。但是,此方法有效,因此当我获得足够的声誉时,我会投票给您答案。
塞巴斯蒂

遗憾的是,这似乎是最好的解决方案-如果该标志设置在将来发生更改,或者您希望能够使用pull刷新其他站点上的内容,那该怎么办?:(。
user1063287

1
如果Google CEO正在阅读此内容,请删除此功能。似乎不能轻易且全面地禁用它,我认为这是并非所有Web应用程序都需要的Web应用程序“功能”。
user1063287

8

我使用MooTools,并创建了一个Class来禁用对目标元素的刷新,但是其症结在于(本地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;
});

我们在这里所做的只是找到触摸移动的y方向,如果我们向下移动屏幕并且目标滚动为0,我们将停止该事件。因此,没有刷新。

这意味着我们在每一个“动作”上都开枪,这可能很昂贵,但这是我到目前为止发现的最好的解决方案...


2
用户向下滚动时立即停止观看是安全的,因为刷新拉动不会被触发。同样,如果为scrolltop > 0,则不会触发该事件。在我的实现中,仅当时,我将touchmove事件绑定到。一旦用户向下滚动(),我便解除了绑定。如果用户向上滚动(),则致电。touchstartscrollTop <= 0initialY >= e.touches[0].clientYpreviousY < e.touches[0].clientYpreventDefault
Nicolas Bouliane


5

AngularJS

我已经使用以下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);
        }
    };
});

用户向下滚动时立即停止观看是安全的,因为刷新拉动不会触发。

同样,如果为scrolltop > 0,则不会触发该事件。在我的实现中,仅当时,我将touchmove事件绑定到touchstart上scrollTop <= 0。一旦用户向下滚动(initialY >= e.touches[0].clientY),我便解除了绑定。如果用户向上滚动(previousY < e.touches[0].clientY),则致电preventDefault()

这使我们免于不必要地观看滚动事件,但阻止了过度滚动。

jQuery的

如果您使用的是jQuery,则这是未经测试的等效项。element是一个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);

当然,使用纯JS也可以实现相同的效果。


我不得不用它e.originalEvent.touches[0].clientY来使这项工作。何时仍在努力防止重新加载的逻辑。现在看来,它似乎是随机阻止向上滚动的。感谢您向正确方向提出的提示!
thomas 2015年

指令添加到什么元素?
Fizzix '16

AngularJS指令对我来说效果很好。我们一起使用Framework7和Angular(不会建议这样做),并且某些东西阻止了scrollTop的正确行为。所以我不得不修改将blockScroll添加到元素的时间。但是只想说谢谢!
达斯汀·延森

5

简单的Javascript

我使用标准javascript实现。简单易实现。只需粘贴即可,效果很好。

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

这在Chrome上效果很好,但是在滚动页面顶部的div时,在Safari / iOS 9.2上为我向上滚动时引起了一些问题(在此处复制)。我最终使用了上面Evynbody: {overflow-y:hidden}把戏。
森尼特'16

不能在chrome上使用,而是在firefox示例中起作用embed.plnkr.co/rqbOVSOkKyhAgoHK2sEP 仅在移动设备上打开
vijay

您粘贴的链接在我的android手机上也适用于chrome。它不允许在拉动时刷新。您正在使用哪个版本的android / ios进行测试?
Sacky San

2
在Chrome 56中,您需要设置“ passive”:“ false”以使其起作用:document.addEventListener('touchstart',touchstartHandler,{Passive:false}); document.addEventListener('touchmove',touchmoveHandler,{被动:假});
安东·库兹明

4

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

观看此演示:https : //jsbin.com/pokusideha/quiet


您真的在使用chrome的手机上测试过吗?
Gregor Voinov


3

我发现设置您的身体 CSS 溢出-y:隐藏是最简单的方法。如果您确实希望拥有滚动应用程序页面,则可以仅使用具有滚动功能的div容器。


似乎不可能用一条线将其修复,但是像吊饰一样工作,非常感谢!
伊格纳西奥(Ignacio Ara)

2

请注意,overflow-y不是继承的,因此您需要在所有块元素上进行设置。

您可以通过jQuery做到这一点,方法是:

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

在其他答案中,这个确实很有帮助。谢谢。将此行添加到CSS中。身体{overflow-y:隐藏;}
Sarin JS

2

几个星期以来,我发现我用来禁用Chrome刷新操作的javascript函数不再起作用。我已经解决了这个问题:

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

纯js解决方案。

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

我所做的是在touchstarttouchend/ touchcancel事件中添加了以下内容:

scrollTo(0, 1)

由于chrome如果不在scrollY位置上,则不会滚动,0这将防止chrome进行拉动刷新。

如果仍然无法使用,请在页面加载时尝试这样做。


0

我用以下方法解决了从下拉到刷新的问题:

html, body {
    width: 100%;
    height: 100%;
    overflow: hidden;
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.