【问题标题】:Android Keyboard shrinking the viewport and elements using unit vh in CSSAndroid键盘使用CSS中的单位vh缩小视口和元素
【发布时间】:2015-10-06 06:44:15
【问题描述】:

我遇到了一个非常奇怪和独特的问题。

由于项目的性质,我所有的页面都使用 vh 和 vw CSS 单位而不是 px。

问题:在 Android 平板电脑上,当您触摸输入字段时,默认键盘会推动视图端口,从而导致页面和页面中的所有元素缩小。

在 ipad 上不存在此问题,因为键盘与屏幕重叠并且不推动屏幕。

寻找任何解决方案来避免Android键盘不推送浏览器的视口并保持原始大小。

注意:我剩下的唯一选择是避免键盘推动视口,我将无法更改 CSS 单位或使用 xml、清单。这些是遇到此问题的网页。

【问题讨论】:

    标签: javascript android html css


    【解决方案1】:

    我知道这是一个老问题,但我在我的应用程序中遇到了完全相同的问题。我找到的解决方案相当简单。 (我的应用在 Angular 中,所以我把它放在 app.component 的 ngOnInit 函数中,但 document.ready() 或任何其他“初始化完成”回调应该可以通过适当的实验正常工作)

    setTimeout(function () {
            let viewheight = $(window).height();
            let viewwidth = $(window).width();
            let viewport = document.querySelector("meta[name=viewport]");
            viewport.setAttribute("content", "height=" + viewheight + "px, width=" + viewwidth + "px, initial-scale=1.0");
        }, 300);
    

    这会强制视口元显式设置视口高度,而硬编码

    <meta name="viewport" 
    content="width=device-width, height=device-height, initial-scale=1">
    

    不起作用,因为打开 Android 的软键盘时设备宽度和设备高度会发生变化。

    【讨论】:

    • 完美解决方案!像魅力一样工作。我尝试了szanata.com,这是一个分成多个部分的登录页面,每个部分的高度为 100vh。谢谢!
    • 此解决方案运行良好,但我发现了一个小问题。在移动设备仿真模式下使用 chrome 开发人员工具时,window.innerHeightwindow.innerWidth(或 $(window).height()$(window).width())的值设置不正确。所以如果你正在使用这个工具,当你的代码在开发浏览器中运行时,你应该查询window.visualViewport.heightwindow.visualViewport.width
    • 如果页面小于或等于视口,则窗口在输入时停止滚动
    • 这对我不起作用。我可以确认在元标记中设置了高度和宽度(使用 devtools 远程设备),但它仍然按比例缩小,因此用户无法看到选定的输入。
    • 你不需要指定“px”。
    【解决方案2】:

    根据 Tyler 的问题,这是脚本的香草版本,似乎更简洁:

    addEventListener("load", function() {
        var viewport = document.querySelector("meta[name=viewport]");
        viewport.setAttribute("content", viewport.content + ", height=" + window.innerHeight);
    })
    

    如果你在元标记声明之后使用它,你甚至可以摆脱那个addEventListener

    var viewport = document.querySelector("meta[name=viewport]");
    viewport.setAttribute("content", viewport.content + ", height=" + window.innerHeight);
    

    【讨论】:

    • 你是上帝,我把它放在我的元标签声明下的脚本标签中,它工作得很好,非常感谢你
    • 像 React 页面中的魅力一样工作。
    • 感谢您不使用 jQuery,哈哈。
    【解决方案3】:

    这是一个考虑屏幕方向变化的更完整的解决方案:

    // Original viewport definition, note the "id" that I use to modify the viewport later on:
    <meta name="viewport" id="viewport" content="width=device-width, height=device-height, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/>
    
    <script>
    // Global boolean variable that holds the current orientation
    var pageInPortraitMode;
    
    // Listen for window resizes to detect orientation changes
    window.addEventListener("resize", windowSizeChanged);
    
    // Set the global orientation variable as soon as the page loads
    addEventListener("load", function() {
      pageInPortraitMode = window.innerHeight > window.innerWidth;
      document.getElementById("viewport").setAttribute("content", "width=" + window.innerWidth + ", height=" + window.innerHeight + ", initial-scale=1.0, maximum-scale=1.0, user-scalable=0");
    })
    
    // Adjust viewport values only if orientation has changed (not on every window resize)
    function windowSizeChanged() {
      if (((pageInPortraitMode === true) && (window.innerHeight < window.innerWidth)) || ((pageInPortraitMode === false) && (window.innerHeight > window.innerWidth))) {
        pageInPortraitMode = window.innerHeight > window.innerWidth;
        document.getElementById("viewport").setAttribute("content", "width=" + window.innerWidth + ", height=" + window.innerHeight + ", initial-scale=1.0, maximum-scale=1.0, user-scalable=0");
      }
    }
    </script>
    

    【讨论】:

      【解决方案4】:

      我最近遇到了同样的问题,我花了一些时间找到一个好的解决方案。 我正在使用 html5、css3 和 angularjs 设计一个科尔多瓦应用程序。但此外,我希望我的应用程序适合每个屏幕,而无需编写媒体查询的音调和最终无法读取的 css。我从视口和 vh 开始,但键盘坏了一切。

      所以你必须使用的只是一个像这样的小 javascript(这里是 jquery):

      $("html").css({"font-size": ($(window).height()/100)+"px"});
      

      好了,现在您可以像使用“vh”一样使用“rem”了,只是视口不会影响字体大小。 "Rem" 仅在 html 根字体大小上设置,我们只需使用 jquery 将其设置为屏幕高度的 1%。

      希望这会有所帮助!

      编辑 1: 我刚刚遇到一个新问题,所以我在这里给出我的解决方案。大多数时候,智能手机对字体大小都有一个最小限制。 您必须更改所有 rem 值,并将其除以 3 或 4。 然后,您必须使用以下命令更改 javascript:

      $("html").css({"font-size": ($(window).height()/25)+"px"}); /*(this is if you divide with 4)*/
      

      如果你使用 SASS 就更容易了,你可以创建一个 rem 函数来为你做除法。

      【讨论】:

        【解决方案5】:

        迟到了将近一年,但我也想分享我对这个越来越重要的问题的解决方案。

        我创建了一个小的 JS 函数 SET,它在 DOM 完成后加载。

        当视口高度减小时,分配给特殊类(在本例中为“.pheight”)的每个元素都不会调整大小。只有当视口高度增加或视口宽度发生变化时才允许调整大小。

        所以在我的应用程序中它可以完美运行!

          var docwidth = window.innerWidth;
          var docheight = window.innerHeight;
          function pheigt_init() {    
            pheigt_set_prevent_height();
            window.onresize = function() {
                if (docwidth !== window.innerWidth || docheight < window.innerHeight) {
                    pheigt_upd_prevent_height();
                }
            };
          }
          function pheigt_set_prevent_height() {
            document.querySelectorAll('.pheight').forEach(function(node) {
             node.style.height = node.offsetHeight + 'px';
            });
          }
          function pheigt_upd_prevent_height() {
            document.querySelectorAll('.pheight').forEach(function(node) {
                node.style.removeProperty('height');
            }); 
            setTimeout(function(){ pheigt_set_prevent_height(); }, 100);
            docheight = window.innerHeight;
            docwidth = window.innerWidth;
          }
          document.addEventListener('DOMContentLoaded', pheigt_init());
        

        【讨论】:

          【解决方案6】:

          在 Angular 4+ 中

          import {Meta} from "@angular/platform-browser";
          
          
          constructor(private metaService: Meta){}
          
          ngOnInit() {
            this.metaService.updateTag({
            name: 'viewport',
              content: `height=${this.height}px, width=${this.width}px, initial-scale=1.0`
            },
            `name='viewport'`
          );
          }

          【讨论】:

            【解决方案7】:

            您可以使用似乎不受此问题影响的 % 或 vw(由于明显原因未受影响),即使是高度。

            【讨论】:

              【解决方案8】:

              也许需要使用函数刷新视口高度(或只是高度)?

              const reference = useRef();
              
              function avoidKeyboard(){
                  setTimeout(
                      ()=>{reference.current.querySelector("#win").style.height = "calc(100vh)"}
                  ,2000)
              }
              
              return (
                  <ref={reference} div>
                     <input type="text" id="win" onFocus={avoidKeyboard} onBlur={avoidKeyboard}/>
                  </div>
              )
              

              【讨论】:

                【解决方案9】:

                只在 meta 中使用 'shrink-to-fit=no' :

                <head>
                   <meta content="width=device-width, initial-scale=1, shrink-to-fit=no" name="viewport">
                 </head>
                

                【讨论】:

                  【解决方案10】:

                  同样的问题让我步履蹒跚。我没有找到任何 css 解决方案或解决方法来解决问题。

                  但是,如果您可以使用 JQuery(或几乎是 JavaScript),我有一些代码可以用来解决它。

                  var viewportHeight = $(window).height();
                  var viewportWidth = $(window).width();
                  $('body,html').css("height",viewportHeight); //if vh used in body/html too
                  $('.someClass').css("height",viewportHeight*0.12);// or whatever percentage you used in vh
                  $('#someId').css("width",viewportWidth*0.12);
                  

                  嗯,这只是一个例子,你可以使用百分比,你需要的jQuery标识符。

                  PD:有一个提示可以提供您的信息。将代码放在 html 的最后或 $(document).ready(function() { }); 中,如果您需要响应式设计,也将其放在orientationchange 事件中;这边。

                  $(window).on("orientationchange",function(event){ window.setTimeout(function(){
                  var viewportHeight = $(window).height();
                  var viewportWidth = $(window).width();
                  $('body,html').css("height",viewportHeight);
                  $('.someClass').css("height",viewportHeight*0.12);
                  $('.someClass').css("width",viewportWidth*0.09);
                  $('#someId').css("height",viewportHeight*0.1);
                  }}, 450);});
                  

                  我在上面放了一个 450 毫秒的计时器,因为执行方向更改的设备有延迟。

                  对不起我的英语, 干杯

                  【讨论】:

                    猜你喜欢
                    • 2016-01-02
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2015-07-22
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多