Запрет прокрутки в мобильном браузере без фокусировки ввода

Я использую protectDefault() при сенсорном запуске в документе, чтобы предотвратить прокрутку на странице. К сожалению это мешает слишком много. Пользователь больше не может фокусировать ввод (и открывать программную клавиатуру). Используя jQuery focus(), я могу сфокусировать ввод на сенсорном запуске. Это открывает программную клавиатуру на iOS (большую часть времени), но никогда на Android.

Фон:

У меня есть веб-страница, которую я хочу сделать максимально похожей на мобильное приложение. Я действительно только касаюсь Android и iOS, но любой форм-фактор. Я начинаю с того, что делаю содержимое страницы точно такого же размера, как размер экрана. Это приятно, пока пользователь не положит палец на страницу. Мне нужно предотвратить пользовательскую прокрутку. Следующий код выполняет это, но немного по-разному в двух операционных системах.

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

В iOS это предотвращает упругую прокрутку: когда пользователь может раскрыть текстуру позади веб-страницы, пытаясь прокрутить страницу. Эта функция хороша для обычной веб-страницы, но в моем случае она отвлекает от UX.

На Android предотвращает раскрытие удобного хака, который я использую, чтобы скрыть адресную строку. Браузеры Android начинаются с видимой адресной строки, но когда пользователь прокручивает страницу вниз, она исчезает. Чтобы программно заставить браузер скрыть адресную строку, просто добавьте эту строку кода в вашу функцию, вызываемую при загрузке.

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

Это хакерский (но также единственный) способ сообщить браузеру Android, что мы прокрутили, и адресная строка больше не нужна.

Если на документе не действует веб-браузер protectDefault, прокрутка Android будет прокручиваться, и можно будет открыть адресную строку.

Таким образом, у обеих ОС есть веская причина, чтобы этот метод warnDefault () вызывался при каждом сенсорном запуске в документе, но он слишком много предотвращает. Нажатие на поле ввода ничего не делает. Использование вызова jQuery focus () может помочь, но открывает программную клавиатуру только на iOS, но не на Android.

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

Как я могу предотвратить прокрутку страницы, но использовать встроенные функции браузера для выделения поля ввода?

Примечание: этот код

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

является ошибкой, потому что пользователь все еще может прокручивать страницу, пока первоначальное прикосновение происходит из поля ввода.

3 ответа

Я на самом деле решил эту проблему в другом проекте, забыл об этом и запомнил это до конца.

Они ключ, чтобы просто сделать это на TouchMove.

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

Тем не менее, protectDefault на сенсорном запуске делает все, что угодно, например, предотвращает сохранение изображения в слайд-шоу с поддержкой жестов. Мои проекты также включают это.

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

Если у кого-то есть предложения по дополнительному контенту или как его переформатировать, чтобы он мог охватить большую аудиторию, это было бы здорово. Я никогда не видел контент, который у меня есть, все в одном месте, поэтому я чувствовал, что он должен быть на SO.

Простой ответ на ваш вопрос: не используйте "protectDefault", вместо этого используйте свойство 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 Хороший вопрос

Объедините два!

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

Это, вероятно, тоже не идеально, и я особенно обеспокоен тем, что первая функция предотвратит переход по ссылкам, но я оставлю это другим, чтобы делать обширные тесты.

Другие вопросы по тегам