禁用Android的chrome pull-down-to-refresh功能

时间:2015-03-12 11:10:54

标签: android html html5 google-chrome meta-tags

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

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

该应用程序主要用于Android手机和Chrome浏览器。此外,该网站保存在主屏幕上,因此Android管理整个应用程序(使用WebView我猜)。

Chrome Beta(我认为还有Android系统WebView)引入了“下拉刷新”功能(See this link for example)。

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

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

我知道此功能仅在Chrome测试版中可用,但我感觉这也是稳定的应用程序。

谢谢!

编辑:我已卸载Chrome测试版,现在可以使用稳定的Chrome打开固定到主屏幕的链接。因此,固定链接始于Chrome,而不是webview。

编辑:今天(2015-03-19),下拉到刷新已经到了稳定的镀铬。

编辑:来自@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指出的那样,我希望将来有一个网站清单解决方案(和/或元标记)。

此外,欢迎对上述代码提出建议。

15 个答案:

答案 0 :(得分:138)

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

  1. preventDefault触摸序列的某些部分,包括以下任何一种(按破坏性最小到破坏性最小的顺序):
    • 一个。整个触摸流(不理想)。
    • 湾所有顶级过度触摸的摩托车。
    • ℃。第一个顶部过度滚动触摸移动。
    • d。第一个顶部过度滚动触摸仅在1)当页面y滚动偏移为零时发生初始触摸开始并且2)触摸移动将导致顶部过度滚动时才移动。
  2. 将“touch-action: none”应用于触控目标元素(如果适用),禁用触摸序列的默认操作(包括“拉动 - 刷新”)。
  3. 将“overflow-y: hidden”应用于body元素,必要时使用div作为可滚动内容。
  4. 通过chrome://flags/#disable-pull-to-refresh-effect)在本地停用效果。
  5. See more

答案 1 :(得分:67)

2018 +

的简单解决方案

Chrome 63(2017年12月5日发布)添加了一个css属性来帮助解决这个问题。请仔细阅读this guide by Google,以便了解如何处理它。

这是他们的TL:DR

  

CSS overscroll-behavior属性允许开发人员覆盖   到达时浏览器的默认溢出滚动行为   内容的顶部/底部。用例包括禁用pull-to-refresh   移动功能,消除过卷发光和橡皮筋效果,   并阻止页面内容滚动时的页面内容   模态/重叠。

要使其正常运行,您只需在CSS中添加:

body {
  overscroll-behavior: contain;
}

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

答案 2 :(得分:15)

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

您可以尝试捕捉touchmove事件,但实现可接受的结果的可能性非常小。

答案 3 :(得分:8)

我使用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,我们就会停止事件。因此,没有刷新。

这意味着我们正在开展每一项行动,这可能会很昂贵,但这是迄今为止我找到的最佳解决方案......

答案 4 :(得分: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,则不会触发该事件。在我的实现中,我只在scrollTop <= 0时绑定touchstart上的touchmove事件。一旦用户向下滚动(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也可以实现同样的目标。

答案 5 :(得分:5)

经过几个小时的尝试,这个解决方案适合我

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

答案 6 :(得分:4)

简单的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>

答案 7 :(得分:3)

纯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

答案 8 :(得分:3)

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

答案 9 :(得分:2)

几周以来,我发现我用来禁用Chrome刷新操作的javascript功能不再适用。我已经解决了这个问题:

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

答案 10 :(得分:1)

请注意,overflow-y不会被继承,因此您需要在所有块元素上设置它。

您可以通过以下方式使用jQuery执行此操作:

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

答案 11 :(得分:0)

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

scrollTo(0, 1)

由于chrome不在scrollY位置0上滚动,因此这会阻止chrome进行刷新。

如果它仍然不起作用,请尝试在页面加载时执行此操作。

答案 12 :(得分:0)

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

答案 13 :(得分:0)

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

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

答案 14 :(得分:0)

您可以尝试

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