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


187

我知道在iPhone上的Safari中,您可以通过侦听onorientationchange事件并查询window.orientation角度来检测屏幕的方向和方向变化。

Android手机上的浏览器有可能吗?

明确地说,我想问的是,运行在标准网页上的JavaScript是否可以检测到Android设备的旋转。可以在iPhone上使用,我想知道是否可以在Android手机上完成。

Answers:


214

要检测Android浏览器上的方向变化,请将侦听器附加到上的orientationchangeresize事件window

// Detect whether device supports orientationchange event, otherwise fall back to
// the resize event.
var supportsOrientationChange = "onorientationchange" in window,
    orientationEvent = supportsOrientationChange ? "orientationchange" : "resize";

window.addEventListener(orientationEvent, function() {
    alert('HOLY ROTATING SCREENS BATMAN:' + window.orientation + " " + screen.width);
}, false);

检查window.orientation属性以找出设备的定向方向。使用Android手机,screen.width或者screen.height随着设备旋转而更新。(iPhone并非如此)。


这真的有效吗?我尝试了jQuery $(window).bind(“ orientationchange”,fn); 但是它没有用,我必须使用上面的表格吗?我在窗口中尝试了“ onorientationchange”,它重新设置为false
Ayyash

它运作良好。Ayyash-此处的全部要点是,当不支持“ orientationchange”时,它将退回到“ resize”
Dror 2010年

9
在Droid上这完全是疯了。当手机在横向模式下旋转时,它会警告screen.width320。当手机在纵向模式下旋转时,它会检测到screen.width 569!怎么会??
IgorGanapolsky 2011年

1
只是要澄清一下:那些寻求在iOS也可以使用的解决方案的人应该看一下两位傻瓜或我的答案。
mklement0 2012年

3
无需使用iOS的两位傻瓜黑客。只需在Android上使用screen.width和screen.height,在iOS上使用window.innerWidth和window.innerHeight。
贾斯汀

224

跨不同设备的实际行为是不一致的。resize和directionChange事件可以以不同的顺序以不同的频率触发。另外,某些值(例如screen.width和window.orientation)并非总是在您期望的时候改变。避免使用screen.width-在iOS中旋转时不会更改。

可靠的方法是同时监听resize和directionChange事件(将一些轮询作为安全陷阱),最终您将获得一个有效的Direction值。在我的测试中,将Android设备旋转整整180度时,有时不会触发事件,因此,我还添加了setInterval来轮询方向。

var previousOrientation = window.orientation;
var checkOrientation = function(){
    if(window.orientation !== previousOrientation){
        previousOrientation = window.orientation;
        // orientation changed, do your magic here
    }
};

window.addEventListener("resize", checkOrientation, false);
window.addEventListener("orientationchange", checkOrientation, false);

// (optional) Android doesn't always fire orientationChange on 180 degree turns
setInterval(checkOrientation, 2000);

这是我测试过的四种设备的结果(对ASCII表很抱歉,但这似乎是显示结果的最简单方法)。除了iOS设备之间的一致性外,跨设备还有很多不同之处。注意:事件按触发的顺序列出。

| ================================================= =========================== |
| 设备| 事件已触发| 方向| innerWidth | screen.width |
| ================================================= =========================== |
| iPad 2 | 调整大小 0 | 1024 | 768 |
| (至景观)| 方向变化| 90 | 1024 | 768 |
| ---------------- + ------------------- + ------------ -+ ------------ + -------------- |
| iPad 2 | 调整大小 90 | 768 | 768 |
| (至肖像)| 方向变化| 0 | 768 | 768 |
| ---------------- + ------------------- + ------------ -+ ------------ + -------------- |
| iPhone 4 | 调整大小 0 | 480 | 320 |
| (至景观)| 方向变化| 90 | 480 | 320 |
| ---------------- + ------------------- + ------------ -+ ------------ + -------------- |
| iPhone 4 | 调整大小 90 | 320 | 320 |
| (至肖像)| 方向变化| 0 | 320 | 320 |
| ---------------- + ------------------- + ------------ -+ ------------ + -------------- |
| Droid手机| 方向变化| 90 | 320 | 320 |
| (至景观)| 调整大小 90 | 569 | 569 |
| ---------------- + ------------------- + ------------ -+ ------------ + -------------- |
| Droid手机| 方向变化| 0 | 569 | 569 |
| (至肖像)| 调整大小 0 | 320 | 320 |
| ---------------- + ------------------- + ------------ -+ ------------ + -------------- |
| 三星Galaxy | 方向变化| 0 | 400 | 400 |
| 平板电脑| 方向变化| 90 | 400 | 400 |
| (至景观)| 方向变化| 90 | 400 | 400 |
| | 调整大小 90 | 683 | 683 |
| | 方向变化| 90 | 683 | 683 |
| ---------------- + ------------------- + ------------ -+ ------------ + -------------- |
| 三星Galaxy | 方向变化| 90 | 683 | 683 |
| 平板电脑| 方向变化| 0 | 683 | 683 |
| (至肖像)| 方向变化| 0 | 683 | 683 |
| | 调整大小 0 | 400 | 400 |
| | 方向变化| 0 | 400 | 400 |
| ---------------- + ------------------- + ------------ -+ ------------ + -------------- |

在iOS5模拟器中,如果刷新后旋转,则此代码不会触发。
2012年

1
好答案。previousOrientation应该使用当时的方向进行初始化:var previousOrientation = window.orientation;如果要忽略180度旋转,即不需要区分左右横向和上下颠倒或不同的变体,请添加以下内容作为第一行checkOrientation()if (0 === (previousOrientation + window.orientation) % 180) return;但是,如果没有额外的setTimeout诡计,你只会从这个iOS上,其中一个迅速180度旋转只创建一个有利于单一 orientationchange事件。
mklement0

感谢@mklement,我调整了代码以初始化previousOrientation。
2位傻子

为丰富的信息而欢呼。之所以这样做,是因为您使用cordova时Windows Phone 8.1不会出现调整大小或方向更改事件。诉诸于使用setInterval以及故障保护。
完美的

@ mklement0到目前为止,在Windows Phone 8.1上,window.orientation始终是未定义的。
完美的

39

两位傻瓜的绝妙答案提供了所有背景知识,但让我尝试一下有关如何处理iOS和Android方向变化简要,实用的摘要

  • 如果您只关心窗口尺寸(典型情况) -而不关心特定方向:
    • resize仅处理事件。
    • 在您的处理程序,作用window.innerWidthwindow.InnerHeight唯一。
    • 请勿使用window.orientation-它在iOS上不是最新的。
  • 如果您确实关心特定的方向
    • 处理resizeAndroid上的事件,orientationchangeiOS上的事件。
    • 在您的处理程序中,对window.orientation(和window.innerWidthwindow.InnerHeight)进行操作

与记住先前的方向并进行比较相比,这些方法提供了一些好处:

  • 仅维度方法也可以在桌面浏览器上开发,该浏览器可以模拟移动设备(例如Chrome 23)(window.orientation在桌面浏览器上不可用)。
  • 不需要全局/匿名文件级功能包装器级变量。

问题是,当调整大小或方向事件触发window.innerWidth报告错误且Droid设备时
albanx 2015年

@albanx这仍然是iOS上的镀铬的一个问题:/ Safari是细寿
oldboy

12

您始终可以收听窗口调整大小事件。如果在这种情况下,窗口从大于宽的窗口变为大于宽的窗口(反之亦然),则可以确定电话方向刚刚改变。


那是个好主意,我会尝试的(并请我的朋友用Android手机进行测试!)
philnash

我刚刚意识到这种方法并不能给我电话的方向。我会知道它是人像还是风景,但是如果它是上下颠倒或已向左或向右旋转则不会。还有其他想法吗?
philnash

我不确定这怎么可能...为什么您需要知道手机是否倒置?手机的浏览器位于顶部,并且网页将朝向浏览器的顶部。任何有两个大脑细胞摩擦在一起的用户,如果要颠倒看网页,只会翻开手机
Joel Mueller

1
有点苛刻。我很想知道,以便可以根据屏幕的方向显示不同的内容,最多可以显示4个不同的页面,要求浏览器知道它是否已旋转0、90、180和270度。在iPhone上的JavaScript中,这一切都是可能的,这就是我要问的原因。
philnash

我仍然很难想象当将其渲染的设备旋转270度时,网页可以有效地执行哪些操作,但是如果您说您有一个有效的用例,我就不会打扰。在这种情况下:很抱歉,但是我不知道Android浏览器是否提供了这种详细程度。
乔尔·穆勒

3

在HTML5中是可能的。
您可以在这里阅读更多内容(并尝试现场演示):http : //slides.html5rocks.com/#slide-orientation

window.addEventListener('deviceorientation', function(event) {
    var a = event.alpha;
    var b = event.beta;
    var g = event.gamma;
}, false);

它还支持桌面浏览器,但始终返回相同的值。


4
尽管我认为该事件也可以用于检测方向变化,但实际上它更适合访问运动传感器。
勒内

在我的Android Galaxy S2上,普通浏览器或Dolphin浏览器均不支持该功能。但与移动Firefox兼容。
爱德华多

3

我有同样的问题。我正在为Adroid设备使用Phonegap和Jquery mobile。要正确调整大小,我必须设置一个超时时间:

$(window).bind('orientationchange',function(e) {
  fixOrientation();
});

$(window).bind('resize',function(e) {
  fixOrientation();
});

function fixOrientation() {

    setTimeout(function() {

        var windowWidth = window.innerWidth;

        $('div[data-role="page"]').width(windowWidth);
        $('div[data-role="header"]').width(windowWidth);
        $('div[data-role="content"]').width(windowWidth-30);
        $('div[data-role="footer"]').width(windowWidth);

    },500);
}

2

解决方法如下:

var isMobile = {
    Android: function() {
        return /Android/i.test(navigator.userAgent);
    },
    iOS: function() {
        return /iPhone|iPad|iPod/i.test(navigator.userAgent);
    }
};
if(isMobile.Android())
    {
        var previousWidth=$(window).width();
        $(window).on({
        resize: function(e) {
        var YourFunction=(function(){

            var screenWidth=$(window).width();
            if(previousWidth!=screenWidth)
            {
                previousWidth=screenWidth;
                alert("oreientation changed");
            }

        })();

        }
    });

    }
    else//mainly for ios
    {
        $(window).on({
            orientationchange: function(e) {
               alert("orientation changed");
            }   
        });
    }

这是最适合我的解决方案,我知道它不是100%准确的,但是您可以使用以下方法检测水平还是垂直:var screenWidth = $(window).width(); var screenHeight = $(window).height(); if(screenWidth> screenHeight){doSomething(); }
math0ne 2015年

这是我在笨拙的Android平板电脑上的解决方案。window.onresize,attachevent和addeventlistener在多个事件(调整大小,onresize,orientationchange,deviceorientation)上失败。仅Jquery $(window).on()有效。
乐高

1

另一个陷阱-某些Android平板电脑(我相信是Motorola Xoom和我正在进行测试的低端Elonex,也许还有其他平板电脑)已设置了加速度计,以使window.orientation == 0在LANDSCAPE模式下而不是纵向模式!


1

您可以尝试与所有浏览器兼容的解决方案。

以下是orientationchange兼容性图片: 兼容性 因此,我编写了一个orientaionchangepolyfill,它是基于@media属性来修复directionchange实用程序库的—directionchange -fix

window.addEventListener('orientationchange', function(){
 if(window.neworientation.current === 'portrait|landscape'){
    // do something……
 } else {
    // do something……
 }
}, false);

0

值得注意的是,在我的Epic 4G Touch上,必须先将Webview设置为使用WebChromeClient,然后才能进行任何javascript android调用。

webView.setWebChromeClient(new WebChromeClient());

0

跨浏览器方式

$(window).on('resize orientationchange webkitfullscreenchange mozfullscreenchange fullscreenchange',  function(){
//code here
});

-1

对两位傻瓜的回答有一点贡献:

如droid手机上表中所述,“ orientationchange”事件比“ resize”事件更早触发,从而阻止了下一个resize调用(由于if语句)。宽度属性仍未设置。

一种解决方法虽然可能不是一个完美的解决方法,但可能是不触发“ orientationchange”事件。可以通过将“ orientationchange”事件绑定包装在“ if”语句中来存档:

if (!navigator.userAgent.match(/android/i))
{
    window.addEventListener("orientationchange", checkOrientation, false);
}

希望能帮助到你

(测试是在Nexus S上完成的)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.