如果不是body元素,Android无法正确滚动输入焦点

Dom*_*nic 16 android scroll google-chrome focus input

当移动浏览器调出键盘时,它会尝试移动滚动条,以便输入仍在视图中.

在iOS Safari上,它似乎通过查找最近的滚动父级来正确执行此操作.

在Android原生或Chrome移动浏览器上,它似乎只是尝试身体元素然后放弃,因此焦点输入隐藏在键盘下方.

 如何打破它

设置overflow-y: hidden在body元素上.创建一个可滚动的容器并在其中放置一个表单.

当您选择靠近屏幕底部的元素时,它将被键盘遮挡.

演示

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>
Run Code Online (Sandbox Code Playgroud)

任何想法如何解决这一问题?它需要一些浏览器检测和杂乱的黑客攻击吗?

Ser*_*rge 49

这是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);
      }
   })
}
Run Code Online (Sandbox Code Playgroud)

  • 请注意,Android 4.4和5也需要这个,而不仅仅是"4. [0-3]" (2认同)
  • 你应该更喜欢[`document.activeElement.scrollIntoView()`](https://developer.mozilla.org/en/docs/Web/API/Element/scrollIntoView),这也得到了其他浏览器的更好支持. (2认同)

Zac*_*ton 9

Serge的答案很棒,但我做了一些改进,为我改进了它.

问题出现在Android 6上,所以我把它添加到支票中,我需要修复工作textareas以及输入.

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);
      }
   })
}
Run Code Online (Sandbox Code Playgroud)

如果有人需要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();
                });
            }
        });
    }
});
Run Code Online (Sandbox Code Playgroud)


小智 6

如果可以节省任何人的时间,则提供轻微的修改:

  • 无需指定 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();
         }
      })
    } 
    
    Run Code Online (Sandbox Code Playgroud)