6

我在文档的 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();
    }
});

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

4

3 回答 3

10

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

他们的关键是在touchmove上做。

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

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

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

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

于 2012-09-18T21:09:10.040 回答
0

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

于 2014-10-01T10:21:22.173 回答
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();
    }
});

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

于 2013-06-08T16:33:42.637 回答