禁用 android 的 chrome 下拉刷新功能

Posted

技术标签:

【中文标题】禁用 android 的 chrome 下拉刷新功能【英文标题】:Disabling android's chrome pull-down-to-refresh feature 【发布时间】:2015-05-14 12:23:17 【问题描述】:

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

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

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

Chrome Beta(我认为也是 Android System WebView) 引入了“下拉刷新”功能 (See this link for example)。

这是一个方便的功能,但我想知道是否可以使用一些元标记(或 javascript 内容)禁用它,因为用户在导航列表时可以轻松触发刷新,并且重新加载整个应用程序。

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

我知道这个功能仍然只在 Chrome 测试版中可用,但我感觉它也登陆了稳定的应用程序。

谢谢!

编辑:我已经卸载了 Chrome Beta,固定到主屏幕的链接现在可以使用稳定的 Chrome 打开。所以固定链接以 Chrome 开头,而不是 webview。

编辑:今天(2015 年 3 月 19 日)下拉刷新已进入稳定版 chrome。

编辑:来自@Evyn 的回答我关注this link 并得到了这个可以工作的javascript/jquery 代码。

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

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

欢迎对以上代码提出建议。

【问题讨论】:

是的,这真的很糟糕。处于表格中间并滚动到顶部太远,它刷新并丢失了所有内容。这是一个延迟的默认功能,如果我想刷新,我点击刷新图标! 如果可以在我的网络应用清单中禁用此功能会很好。不幸的是,我的网络应用程序上的每个页面都有可滚动的内容,因此几乎无法在不刷新的情况下进行导航。我有点心动了。 :// 这是个好信息。我讨厌禁用下拉刷新功能的网站。我想开发一项功能,使刷新工作不受页面内容的影响。 作为 Web 开发人员,下拉刷新与数据驱动的网站不兼容,因为它会重新加载应用程序。它使用户无法在不刷新整个页面的情况下滚动到页面顶部。我 100% 支持 Chrome,希望他们删除这个反功能。 我遇到了这个GC“功能”……很多网页,很多表格,一个不小心用手指下拉,这个页面上的数据丢失了!延迟功能 IMO。默认情况下它应该是关闭的,谁需要它然后让代码它。我想知道为什么我的“客户”偶尔会丢失他们在 GC 上的数据... 【参考方案1】:

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

    preventDefault’ing 触摸序列的某些部分,包括以下任何一项(按照破坏性最大到破坏性最小的顺序): 一个。整个触摸流(不理想)。 乙。所有顶部滚动触摸动作。 c。第一个顶部滚动触摸动作。 d.仅当 1) 初始 touchstart 发生在页面 y 滚动偏移量为零时以及 2) touchmove 会导致顶部过度滚动时,才进行第一次顶部过度滚动。 在适当的情况下将“@​​987654323@”应用于以触摸为目标的元素,禁用触摸序列的默认操作(包括下拉刷新)。 将“overflow-y: hidden”应用于 body 元素,如有必要,可使用 div 滚动内容。 通过chrome://flags/#disable-pull-to-refresh-effect在本地禁用效果。

See more

【讨论】:

谢谢@Evyn。我不敢相信这是一个快速修复!我将 body 元素的 CSS 设置为 overflow-y:hidden。 “chrome://flags (disable-pull-to-refresh-effect)”是如何以编程方式完成的? @SomeoneSomewhere 据我所知,这并非不可能。 chrome 设置只能由用户设置 - 否则会带来安全风险 对 body 元素应用“overflow-y: hidden”,使用 div 滚动内容对我有用。 选项 3 太棒了,尝试了几十个选项,最后最简单的选项有效,非常感谢!【参考方案2】:

2019+ 的简单解决方案

Chrome 63 添加了一个 CSS 属性来帮助解决这个问题。阅读this guide by Google 以了解如何处理它。

这是他们的 TL:DR

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

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

body 
  overscroll-behavior: contain;

目前 Chrome、Edge 和 Firefox 也只有 supported,但我相信 Safari 会尽快添加它,因为它们似乎完全支持服务工作者和 PWA 的未来。

【讨论】:

这是最新的答案 有其他人注意到这会延迟“添加到主屏幕”chrome 横幅的出现吗? 必须将其应用到 html 元素才能禁用它 这仅适用于 Android , IO 上的 Chrome 仍然显示发光效果 + 原生拉动刷新 developers.google.com/web/updates/2017/11/overscroll-behavior这个链接也可以解释的更好【参考方案3】:

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

您可以尝试捕捉touchmove 事件,但获得可接受结果的机会非常渺茫。

【讨论】:

谢谢凯文的回答。我不能接受这个作为接受的,因为我正在寻找不依赖于用户的东西。但是这种方法有效,所以当我获得足够的声誉时,我会支持你的答案。 很遗憾,这似乎是最好的解决方案 - 如果该标志设置在未来发生变化,或者您希望能够在其他站点上使用 pull 刷新...很惊讶这可以不能以编程方式控制。 :(。 如果 Google 的 CEO 正在阅读此内容,请删除此功能。它似乎并不能轻松全面地禁用,并且在我看来是并非所有 Web 应用程序都想要的 Web 应用程序“功能”。【参考方案4】:

我使用 MooTools,并且我创建了一个类来禁用目标元素的刷新,但它的关键是(原生 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;
);

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

这意味着我们会在每一个“动作”上开火,这可能会很昂贵,但这是我迄今为止找到的最佳解决方案......

【讨论】:

一旦用户向下滚动,停止观看是安全的,因为拉动刷新没有被触发的机会。同样,如果scrolltop > 0,则不会触发该事件。在我的实现中,我将touchmove 事件绑定在touchstart 上,前提是scrollTop <= 0。一旦用户向下滚动(initialY >= e.touches[0].clientY),我就会取消绑定它。如果用户向上滚动(previousY < e.touches[0].clientY),那么我调用preventDefault【参考方案5】:

经过几个小时的尝试,这个解决方案对我有用

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

【讨论】:

没有必要为此使用 jQuery。只需将“touch-action: pan-down”添加到您的 css 代码文件中即可。 在你的css中使用这个:htmltouch-action:pan-down【参考方案6】:

你可以试试这个

body 
  /* Disables pull-to-refresh but allows overscroll glow effects. */
  overscroll-behavior-y: contain;

例子:

https://ebidel.github.io/demos/chatbox.html

完整文档 https://developers.google.com/web/updates/2017/11/overscroll-behavior

【讨论】:

【参考方案7】:

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 &gt; 0,则不会触发该事件。在我的实现中,我在 touchstart 上绑定 touchmove 事件,仅当 scrollTop &lt;= 0 时。一旦用户向下滚动(initialY &gt;= e.touches[0].clientY),我就会取消绑定它。如果用户向上滚动(previousY &lt; e.touches[0].clientY),那么我调用preventDefault()

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

jQuery

​​>

如果您使用的是 jQuery,则这是 untested 等效项。 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 来完成这项工作。仍在为防止重新加载的逻辑when而苦苦挣扎。现在它似乎随机阻止向上滚动......感谢正确方向的提示! 指令添加到什么元素? AngularJS 指令对我来说效果很好。我们一起使用 Framework7 和 Angular(不建议这样做),并且某些东西阻止了 scrollTop 的正确行为。所以我不得不修改何时将 blockScroll 添加到元素中。但只是想说声谢谢!【参考方案8】:

简单的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 来说效果很好,但是在 Safari/ios 9.2 上滚动页面顶部的 div 时导致了一些问题(转载 here)。我最终使用了来自Evyn above 的body: overflow-y:hidden 技巧。 downvoting as 不适用于 chrome,但适用于 Firefox 示例,embed.plnkr.co/rqbOVSOkKyhAgoHK2sEP 仅在移动设备中打开 您粘贴的链接在我的 android 手机上也可以在 chrome 中使用。它不允许在拉动时刷新。你测试的是哪个版本的android/ios? 从 Chrome 56 开始,您需要设置 passive: false 以使其工作: document.addEventListener('touchstart', touchstartHandler, passive: false ); document.addEventListener('touchmove', touchmoveHandler, passive: false );【参考方案9】:

纯 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 在手机上测试过这个吗?【参考方案10】:

我发现设置 body CSS overflow-y:hidden 是最简单的方法。如果您确实想要一个滚动的应用程序页面,您可以只使用具有滚动功能的 div 容器。

【讨论】:

似乎不可能用一条线来修复它,但它就像一个魅力,非常感谢!【参考方案11】:

注意overflow-y不是继承的,所以需要在所有块元素上设置。

您可以通过以下方式使用 jQuery 完成此操作:

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

【讨论】:

在其他答案中,这个真的很有帮助。谢谢。将此行添加到 css 中。身体溢出-y:隐藏; 【参考方案12】:

几周后,我发现我用来禁用 Chrome 刷新操作的 javascript 函数不再起作用。我做了这个来解决它:

$(window).scroll(function() 
   if ($(document).scrollTop() >= 1) 
      $("html").css(
         "touch-action": "auto"
      );
    else 
      $("html").css(
         "touch-action": "pan-down"
      );
   
);
&lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"&gt;&lt;/script&gt;

【讨论】:

【参考方案13】:

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

【讨论】:

【参考方案14】:

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

scrollTo(0, 1)

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

如果仍然无法正常工作,请尝试在页面加载时也这样做。

【讨论】:

【参考方案15】:

我用这个解决了下拉刷新问题:

html, body 
    width: 100%;
    height: 100%;
    overflow: hidden;

【讨论】:

以上是关于禁用 android 的 chrome 下拉刷新功能的主要内容,如果未能解决你的问题,请参考以下文章

在 Chrome 开发人员工具中,如何禁用刷新元素周围的突出显示?

为 DropdownList 禁用 Chrome 自动填充

android 下拉刷新怎么实现

怎么自定义android 下拉刷新动画

android ListView 做下拉刷新 下拉跳到第一项怎么解决

android ListView 做下拉刷新 下拉跳到第一项怎么解决