【发布时间】:2012-09-20 12:48:29
【问题描述】:
目标:
找到设备的最大视口高度,包括address bar 的空间,以便我们可以动态调整最小主体的大小并将我们的内容向上推。
问题:
移动浏览器以不同方式处理方向状态,并以不同方式在方向变化时更新 DOM 属性。
Detect rotation of Android phone in the browser with JavaScript
对于 Android 手机,screen.width 或 screen.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 |
因此,很明显要找到最大视口高度,无论方向如何,使用单个函数返回设备的最大高度在一系列设备上永远不会保持不变。
我发现的其他不能让这两个发挥得很好的问题:
-
window.devicePixelRatio属性可能返回不一致的高度 除以window.outerHeight时。 - 需要使用延迟
window.setTimeout(function() {}, time)来让 DOM 元素在方向更改后有机会更新。 -
window.outerHeight不会更新 iOS 设备的方向更改。使用screen.availHeight作为后备,将底部导航栏作为总高度。 - 使用
#header、#content、#footer结构会强制您动态重新计算#content{min-height},以便在body动态更新时将#footer向下推。
解决方案:
我们先来看看DIV结构:
<style>
#header,#content,#footer{width:100%;}
</style>
<body>
<div id="header"></div>
<div id="content"></div>
<div id="footer"></div>
</body>
我们希望防止设备自行扩展:
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
我们需要帮助才能返回最大视口高度并隐藏 iOS 的地址栏:
<script src="iOS.js" type="text/javascript"></script>
然后检测设备是否支持方向更改并使用调整大小作为后备:
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";
野兽的肚子:
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);
}
}
为页面加载和方向事件添加事件监听器:
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);
证据在布丁中:
iPhone 4 和 4s 纵向和横向
Android 纵向和横向
这里的目标是缩小此解决方案或使其更好。
【问题讨论】:
-
>> 请不要建议媒体查询。为什么不?您可以用来完成此任务的一种(非常hacky)方法是拥有两个不同方向的CSS文件,并在您认为方向改变时使用javascript检查元素宽度。
-
@Christian 高度正在动态计算以支持跨浏览器的液体布局。我需要为几个元素“重新计算”高度。媒体查询被用在可以使用的地方,这不是这些地方之一。
-
首先,如果你手动计算高度,那么布局不是“液体”。其次,我看到你的问题是计算高度而不是检测变化,这是正确的吗?如果是这样,那么我的第一个怀疑是您需要 outerHeight 属性。
-
@Christian 我不会和你争论你认为我的问题是什么。我告诉你我的构建确实是流动的,但是有些元素正在动态计算,因此父元素包含的那些子元素也需要动态计算。 outerHeight 与问题无关。问题是方向更改事件不会在移动 safari 浏览器中获取高度/宽度 DOM 更改。谢谢你的努力。
标签: javascript android html ios mobile