防止在移动浏览器上滚动,而不会阻止输入聚焦

时间:2012-09-18 21:09:10

标签: javascript android ios browser preventdefault

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

背景

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

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

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

在Android上,防止我用来隐藏地址栏的方便黑客的启示。 Android浏览器以地址栏可见开头,但当用户向下滚动页面时,它会消失。要以编程方式强制浏览器隐藏地址栏,只需将此行代码添加到您在load中调用的函数。

$('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();
    }
});

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

3 个答案:

答案 0 :(得分:8)

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

他们的关键是在touchmove上做到这一点。

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

但是,touchstart上的preventDefault会执行各种不错的操作,例如在启用手势的幻灯片中阻止图像保存菜单。我的项目也包括这个。

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

如果有人对其他内容有一些建议,或者如何重新格式化,以便能够吸引更多的观众。我从来没有在一个地方看到过这里的内容,所以我觉得它需要在SO上。

答案 1 :(得分:0)

结合两个!

// 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();
    }
});

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

答案 2 :(得分:0)

您的问题的简单答案是不要使用“preventDefault”而是使用pointer-events 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好问题