javascript - 方向更改Android和iOS后的最大视口高度

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12643314/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 16:45:27  来源:igfitidea点击:

javascript max viewport height after orientation change Android & iOS

javascriptandroidhtmliosmobile

提问by Dan Kanze

The Goal:

目标:

To find the max viewport height of a device including the space of the address barso that we can dynamically resize the min-body and push our content up.

找到设备的最大视口高度,包括空间,address bar以便我们可以动态调整最小主体的大小并将我们的内容向上推。

The Problem:

问题:

Mobile browsers handle orientation states differently and update DOM properties on orientation change differently.

移动浏览器以不同的方式处理方向状态,并在不同的方向改变时更新 DOM 属性。

Detect rotation of Android phone in the browser with JavaScript

使用 JavaScript 在浏览器中检测 Android 手机的旋转

With Android phones, screen.widthor screen.heightalso updates as the device is rotated.

使用 Android 手机,screen.widthscreen.height随着设备旋转而更新。

|==============================================================================|
|     Device     | Events Fired      | orientation | innerWidth | screen.width |
|==============================================================================|
| iPad 2         | resize            | 0           | 1024       | 768          |
| (to landscape) | orientationchange | 90          | 1024       | 768          |
|----------------+-------------------+-------------+------------+--------------|
| iPad 2         | resize            | 90          | 768        | 768          |
| (to portrait)  | orientationchange | 0           | 768        | 768          |
|----------------+-------------------+-------------+------------+--------------|
| iPhone 4       | resize            | 0           | 480        | 320          |
| (to landscape) | orientationchange | 90          | 480        | 320          |
|----------------+-------------------+-------------+------------+--------------|
| iPhone 4       | resize            | 90          | 320        | 320          |
| (to portrait)  | orientationchange | 0           | 320        | 320          |
|----------------+-------------------+-------------+------------+--------------|
| Droid phone    | orientationchange | 90          | 320        | 320          |
| (to landscape) | resize            | 90          | 569        | 569          |
|----------------+-------------------+-------------+------------+--------------|
| Droid phone    | orientationchange | 0           | 569        | 569          |
| (to portrait)  | resize            | 0           | 320        | 320          |

Because of this it is clear that to find the max viewport height no matter what orientation, using a single function to return the max height of a device will never be constant over a range of devices.

正因为如此,很明显,无论什么方向,要找到最大视口高度,使用单个函数返回设备的最大高度在一系列设备上永远不会恒定。

Other problems I have discovered that don't make these two play nice:

我发现的其他问题不会让这两个玩得很好:

  • The window.devicePixelRatioproperty can return inconsistent heights when dividing by window.outerHeight.
  • Delay window.setTimeout(function() {}, time)needs to be used to give DOM elements a chance to update after orientation change.
  • window.outerHeightis not updated on orientation changes for iOS devices. Using screen.availHeightas a fallback includes the bottom nav bar as total height.
  • Using a #header, #content, #footerstructure forces you to dynamically recalculate the #content{min-height}to push the #footerdown when the bodyis dyamically updated.
  • window.devicePixelRatio除以 时,该属性可能返回不一致的高度window.outerHeight
  • window.setTimeout(function() {}, time)需要使用延迟来让 DOM 元素在方向改变后有机会更新。
  • window.outerHeight未更新 iOS 设备的方向更改。使用screen.availHeight作为后备包括底部导航栏为总高度。
  • 使用#header, #content,#footer结构会强制您在动态更新时动态重新计算#content{min-height}#footer向下推body

A Solution:

一个解法:

First let's take a look at DIV structure:

首先我们来看看DIV结构:

<style>
#header,#content,#footer{width:100%;}
</style>

<body>
<div id="header"></div>
<div id="content"></div>
<div id="footer"></div>
</body>

We want to prevent devices from scaling on their own:

我们希望防止设备自行扩展:

<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />

We need help to have the ability to return a max viewport height and hide address bar for iOS:

我们需要帮助才能返回最大视口高度并隐藏 iOS 的地址栏:

<script src="iOS.js" type="text/javascript"></script>

http://iosjs.com/

http://iosjs.com/

Then detect if the device supports orientation change and use resize as a fallback:

然后检测设备是否支持方向更改并使用调整大小作为后备:

var iOS = (navigator.userAgent.match(/(iPad|iPhone|iPod)/i) ? true : false);
var android = (navigator.userAgent.match(/Android/i) ? true : false);
var supportsOrientationChange = "onorientationchange" in window;
var orientationEvent = supportsOrientationChange ? "orientationchange" : "resize"; 

The belly of the beast:

兽腹:

function updateOrientation()
{
    var orientation = (window.orientation);

    if(android)
    {
        window.setTimeout(function() {
            window.scrollTo(0,0);
            var size = window.outerHeight/window.devicePixelRatio;
            $('body').css('min-height', size + 'px');
            var headerHeight = $('#header').height();
            var footerHeight = $('#footer').height();
            var contentHeight = size - (headerHeight+footerHeight);
            $('#content').css('min-height', contentHeight + 'px');
            window.scrollTo(0,1);
        }, 200);
    }

    if(iOS)
    {
        window.setTimeout(function(){
            window.scrollTo(0,0);
            var size = iOS_getViewportSize();
            var headerHeight = $('#header').height();
            var footerHeight = $('#footer').height();
            var contentHeight = size.height - (headerHeight+footerHeight);
            $('#content').css('min-height', contentHeight + 'px');
            window.scrollTo(0,1);
        }, 0);
    }
}

Add event listeners for page load and orientation event:

为页面加载和方向事件添加事件侦听器:

if(iOS)
{
    iOS_addEventListener(window, "load", iOS_handleWindowLoad);
    iOS_addEventListener(window, "orientationchange", iOS_handleOrientationChange);
    iOS_addEventListener(window, "resize", iOS_handleReize);
}
addEventListener("load", function() 
{
    updateOrientation();
}, false);
addEventListener(orientationEvent, function() {
    updateOrientation();
}, false);

Proof is in the pudding:

布丁中有证据:

iPhone 4 & 4s Portrait & Landscape

iPhone 4 和 4s 人像和风景

iPhone 4 & 4s PortraitiPhone 4 & 4s Landscape

iPhone 4 & 4s 人像iPhone 4 & 4s 横向



Android Portrait & Landscape

Android 人像和风景

Android PortraitAndroid Landscape

安卓人像安卓景观



The goal here is to minify this solution or make it better.

这里的目标是缩小此解决方案或使其更好。

回答by stubbsy

This is a simple solution that will append the browsers width and height to the document body on load and window resize.

这是一个简单的解决方案,它将在加载和窗口大小调整时将浏览器的宽度和高度附加到文档正文。

jQuery.event.add(window, "load", resize);
jQuery.event.add(window, "resize", resize);

  function resize() 
    {
      var h = jQuery(window).height();
      var w = jQuery(window).width();
      jQuery("body").css({"width": w, "height": h});
    }

回答by frenchie

You could try a self-invoking closure that monitors the change in orientation by itself. Something like this:

您可以尝试使用自调用闭包来自行监控方向的变化。像这样的东西:

(function () {

    var CurrentHeight;

    (function CheckForOrientationChange() {

        //var NewHeight = window.screen.availHeight / window.devicePixelRatio;
        //var NewHeight = $(window).height();    

        var NewHeight = $('#WidthCheck').width();

        if (CurrentHeight && CurrentHeight!== NewHeight ) {

            alert(NewHeight); // change here
        }

        CurrentHeight = NewHeight;

        setTimeout(CheckForOrientationChange, 1000);

    })();

})();

Just drop this into the document ready function. For now it checks every second but you can shorten that interval. The jsfiddle is hereand you can test it by changing the size of the browser to simulate a mobile browser's change and then you can adapt the code to handle your action.

只需将其放入文档就绪功能中即可。现在它每秒检查一次,但您可以缩短该间隔。该的jsfiddle是在这里,你可以通过改变浏览器来模拟移动浏览器的变化的大小对其进行测试,然后你可以适应代码来处理你的动作。

回答by Dawson

Expected values returned in iOS simulator. I can't test for Android at the moment.

iOS 模拟器中返回的预期值。我目前无法测试 Android。

var supportsOrientationChange = "onorientationchange" in window;
var orientationEvent = supportsOrientationChange ? "orientationchange" : "resize";

window.onload = updateOrientation();

window.addEventListener(orientationEvent, function() {
    updateOrientation();
}, false);

function updateOrientation(){
    switch(window.orientation){
    case 0:
    alert(window.outerHeight); // Returns '356' with browser chrome
    break;

    case -90:
    alert('Landscape right');
    break;

    case 90:
    alert(window.outerHeight); // Returns '208' w browser chrome
    break;

    case 180:
    //alert('Portrait view - upside down');
    break;
    }
    var orientation = (window.orientation);
}

(Note: This code will not test in a browser.)

(注意:此代码不会在浏览器中测试。)