【问题标题】:Prevent scrolling on mobile browser, without preventing input focusing防止在移动浏览器上滚动,而不防止输入焦点
【发布时间】:2012-09-11 04:39:01
【问题描述】:

我在文档的 touchstart 上使用 preventDefault() 来防止在页面上滚动。不幸的是,这阻止了太多。用户不能再将焦点放在输入上(并打开软键盘)。使用 jQuery focus(),我可以将焦点放在 touchstart 上的输入上。这会在 iOS 上打开软键盘(大部分时间),但在 Android 上不会。

背景

我想制作一个尽可能像移动应用程序的网页。我只真正关心 Android 和 iOS,但任何形式的因素。我首先使页面中的内容与屏幕大小完全相同。这很好,直到用户将手指放在页面上。我需要防止用户滚动。以下代码实现了这一点,但在两个操作系统上的方式略有不同。

$(document).on('touchstart', function(e) {
    e.preventDefault();
});

在 iOS 上,这可以防止弹性滚动:用户可以通过尝试滚动页面来显示网页背后的纹理。该功能非常适合常规网页,但在我的情况下,它会降低用户体验。

在 Android 上,防止泄露我用来隐藏地址栏的一个方便的 hack。 Android 浏览器开始时地址栏是可见的,但是当用户向下滚动页面时,它就会消失。要以编程方式强制浏览器隐藏地址栏,只需将这行代码添加到加载时调用的函数中即可。

$('html, body').scrollTop(1);

这是告诉 android 浏览器我们已经滚动的一种 hacky(但也是唯一的)方法,并且不再需要地址栏。

如果文档上没有 preventDefault,Android 浏览器将允许滚动并显示地址栏。

因此,两个操作系统都有充分的理由在文档的每个 touchstart 上调用此 preventDefault(),但它阻止的太多。点击输入字段没有任何作用。调用 jQuery focus() 会有所帮助,但只能在 iOS 上打开软键盘,而不是在 Android 上。

$('input').on('touchstart', function() {
    $(this).focus();
});

如何防止页面滚动,但使用浏览器原生功能将焦点放在输入字段上?

注意: 这段代码

$(document).on('touchstart', function(e) {
    if (e.target.nodeName !== 'INPUT') {
        e.preventDefault();
    }
});

存在缺陷,因为只要初始触摸来自输入字段,用户仍然可以滚动页面。

【问题讨论】:

    标签: javascript android ios browser preventdefault


    【解决方案1】:

    您的问题的简单答案是不要使用“preventDefault”,而是使用指针事件 css 属性来禁用滚动元素的滚动。

    输入的 CSS:

    input {
        pointer-events: auto !important;
    }
    

    touchstart 事件监听器:

    document.body.addEventListener('touchstart', function(e) {
        if (e.target.nodeName === 'INPUT') {
            this.style.pointerEvents = 'none';
        }
    });
    

    模糊输入时需要重置指针事件。

    document.body.pointerEvents = 'auto';
    

    +1 好问题

    【讨论】:

    • 所以你要在每个 touchstart 和每个 touchend 上更改 DOM。如果我们考虑表演,也许这不是轻松的方式。
    【解决方案2】:

    将两者结合起来!

    // prevent scrolling from outside of input field
    $(document).on('touchstart', function(e) {
        if (e.target.nodeName !== 'INPUT') {
            e.preventDefault();
        }
    });
    
    // prevent scrolling from within input field
    $(document).on('touchmove', function(e) {
        if (e.target.nodeName == 'INPUT') {
            e.preventDefault();
        }
    });
    

    这可能也不完美,我特别担心第一个功能会阻止链接,但我会留给其他人做广泛的测试。

    【讨论】:

      【解决方案3】:

      我实际上在另一个项目中解决了这个问题,忘记了它,并通过输入这个大部分方式记住了它。

      他们的关键是在 touchmove 上完成。

      $(document).on('touchmove', function(e) {
          e.preventDefault();
      });
      

      然而,touchstart 上的 preventDefault 会做各种好事,比如在启用手势的幻灯片上阻止图像保存菜单。我的项目也包括这个。

      $(document).on('touchstart', function(e) {
          if (e.target.nodeName !== 'INPUT') {
              e.preventDefault();
          }
      });
      

      如果有人对其他内容或如何重新格式化以使其能够覆盖更多受众有一些建议,那就太好了。我从来没有在一个地方看到过我在这里的所有内容,所以我觉得它需要放在 SO 上。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-31
        • 1970-01-01
        • 2020-07-02
        • 2011-10-25
        相关资源
        最近更新 更多