问题描述

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

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

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

Chrome Beta(我也认为 Android 系统 WebView) 已经推出了 「下拉刷新」 功能 (See this link for example) 。

这是一个方便的功能,但我想知道是否可以禁用一些元标记 (或 JavaScript 东西),因为刷新可以轻松触发用户导航列表和整个应用程序重新加载。

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

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

谢谢!

编辑:我已经卸载了 Chrome 测试版,并且固定到主屏幕的链接现在使用稳定的 Chrome 打开。因此,固定链接从 Chrome 开始,而不是使用网络视图。

编辑:今天 (2015-03-19)pull-down-to-refresh 已经来到了稳定的镀 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 指出的,我希望将来能够提供站点清单解决方案 (和/或 meta-tag) 。

此外,欢迎有关上述代码的建议。

最佳解决方案

通过执行以下操作可以有效地防止 pull-to-refresh 效果的默认动作:

  1. 防止触摸序列的某些部分,包括以下任何内容 (以最具破坏性至最不破坏性的顺序):

    • 一个。整个触摸流 (不理想) 。

    • 湾所有顶部过卷动触摸。

    • C 。第一个顶部过卷动 touchmove 。

    • 天。第一个顶部过卷动 touchmove 只有当 1) 初始触摸发生时,页面 y 滚动偏移为零,2) 触摸屏将引起顶部过度卷动。

  2. 在适当的情况下,对 touch-targeted 元素应用 「touch-action:无」,禁用触摸序列的默认动作 (包括 pull-to-refresh) 。

  3. 将 「overflow-y:hidden」 应用于 body 元素,如果需要,可以使用 div 进行可滚动的内容。

  4. 通过 chrome://标志 (disable-pull-to-refresh-effect) 在本地禁用效果。

See more

次佳解决方案

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

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

第三种解决方案

我使用 MooTools,我已经创建了一个类来禁用目标元素上的刷新,但它的关键是 (native 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,我们停止事件。因此,没有刷新。

这意味着我们正在为每个’move’ 开枪,这可能是昂贵的,但是迄今为止我发现的最佳解决方案…

第四种方案

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,事件不会被触发。在我的实现中,我在 touchstart 上绑定 touchmove 事件,只有当 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 也可以实现。

第五种方案

纯 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

参考文献

注:本文内容整合自 Google/Baidu/Bing 辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:薇晓朵技术论坛