Подтвердить что ты не робот

Android не выполняет корректную прокрутку по фокусу ввода, если не элемент тела

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

В iOS Safari, похоже, это делается правильно, если найти родителя прокрутки ближайшего.

В Android-браузере или на мобильном браузере Chrome он просто пытается создать элемент body, а затем сдается, поэтому сфокусированный вход скрыт под клавиатурой.

Как разбить его

Установите overflow-y: hidden в элемент body. Создайте прокручиваемый контейнер и разместите там форму.

Когда вы выбираете элемент в нижней части экрана, он будет скрыт от клавиатуры.

Demo

http://dominictobias.com/android-scroll-bug/

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"/>
    <title>Android scroll/focus bug</title>
    <style>
    html, body {
        margin: 0;
        padding: 0;
        height: 100%;
        overflow: hidden;
    }
    .scroll {
        position: absolute;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;
        overflow-y: scroll;
    }
    input {
        margin-bottom: 20px;
        width: 100%;
    }
    </style>
</head>
<body>

    <div class="scroll">
        <input type="text" value="Input 1">
        <input type="text" value="Input 2">
        <input type="text" value="Input 3">
        <input type="text" value="Input 4">
        <input type="text" value="Input 5">
        <input type="text" value="Input 6">
        <input type="text" value="Input 7">
        <input type="text" value="Input 8">
        <input type="text" value="Input 9">
        <input type="text" value="Input 10">
        <input type="text" value="Input 11">
        <input type="text" value="Input 12">
        <input type="text" value="Input 13">
        <input type="text" value="Input 14">
        <input type="text" value="Input 15">
        <input type="text" value="Input 16">
        <input type="text" value="Input 17">
        <input type="text" value="Input 18">
        <input type="text" value="Input 19">
        <input type="text" value="Input 20">
    </div>

</body>
</html>

Есть идеи, как это исправить? Будет ли это требовать обнаружения браузера и грязных хаков?

4b9b3361

Ответ 1

Это ошибка в собственном браузере Android. Кстати, вход прокручивается в представление после ввода символа на мягкой клавиатуре.

Следующий фрагмент кода, расположенный где-то на странице, должен помочь:

if(/Android 4\.[0-3]/.test(navigator.appVersion)){
   window.addEventListener("resize", function(){
      if(document.activeElement.tagName=="INPUT"){
         window.setTimeout(function(){
            document.activeElement.scrollIntoViewIfNeeded();
         },0);
      }
   })
}

Ответ 2

Ответ от Сержа велик, но у меня было несколько модификаций, которые улучшили его для меня.

Проблема появилась и на Android 6, поэтому я добавил ее в чек, и мне нужно, чтобы исправление работало как для текстовых полей, так и для ввода.

if(/Android [4-6]/.test(navigator.appVersion)) {
   window.addEventListener("resize", function() {
      if(document.activeElement.tagName=="INPUT" || document.activeElement.tagName=="TEXTAREA") {
         window.setTimeout(function() {
            document.activeElement.scrollIntoViewIfNeeded();
         },0);
      }
   })
}

Если кому-то понадобится исправление в Angular 1, вот что я использовал там.

angular.module('<module name>').run(function ($window, $timeout) {
    if(/Android [4-6]/.test($window.navigator.appVersion)){
        $window.addEventListener("resize", function(){
            if(document.activeElement.tagName=="INPUT" || document.activeElement.tagName=="TEXTAREA"){
                $timeout(function() {
                    document.activeElement.scrollIntoViewIfNeeded();
                });
            }
        });
    }
});

Ответ 3

Предлагая небольшую ревизию, если она кого-то кого-то экономит:

  • Не нужно указывать версию Android версии # (менее вероятно, чтобы сломаться, когда ваш пользователь получит Android 7.0 +)
  • Не нужно обертывать setTimeOut
  • MDN советует против .scrollIntoViewIfNeeded bc несовместимости браузера = > .scrollIntoView является работоспособным заменителем с немного большей совместимостью с браузером

    if(/Android/.test(navigator.appVersion)) {
       window.addEventListener("resize", function() {
         if(document.activeElement.tagName=="INPUT" || document.activeElement.tagName=="TEXTAREA") {
           document.activeElement.scrollIntoView();
         }
      })
    } 
    

Ответ 4

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

if(/Android/.test(navigator.appVersion)){
  $('input[type="text"]').attr('autocomplete', "off");
}

что дает гораздо более плавный результат.