javascript max viewport height after orientation change Android & iOS

大城市里の小女人 提交于 2019-12-20 08:30:50

问题


The Goal:

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

The Problem:

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

Detect rotation of Android phone in the browser with JavaScript

With Android phones, screen.width or screen.height also updates as the device is rotated.

|==============================================================================|
|     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.devicePixelRatio property 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.outerHeight is not updated on orientation changes for iOS devices. Using screen.availHeight as a fallback includes the bottom nav bar as total height.
  • Using a #header, #content, #footer structure forces you to dynamically recalculate the #content{min-height} to push the #footer down when the body is dyamically updated.

A Solution:

First let's take a look at DIV structure:

<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:

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

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


Android Portrait & Landscape


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


回答1:


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



回答2:


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

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.)




回答3:


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 here and 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.



来源:https://stackoverflow.com/questions/12643314/javascript-max-viewport-height-after-orientation-change-android-ios

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!