简体   繁体   English

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

[英]Detect rotation of Android phone in the browser with JavaScript

I know that in Safari on an iPhone you can detect the screen's orientation and change of orientation by listening for the onorientationchange event and querying window.orientation for the angle. 我知道在iPhone上的Safari中,你可以通过监听onorientationchange事件和查询window.orientation来检测屏幕的方向和方向的变化。

Is this possible in the browser on Android phones? 这可能在Android手机上的浏览器中出现吗?

To be clear, I am asking whether the rotation of an Android device can be detected by JavaScript running on a standard web page. 为了清楚起见,我问的是,在标准网页上运行的JavaScript是否可以检测到Android设备的旋转。 It is possible on an iPhone, and I wondered whether it could be done for Android phones. 这可能在iPhone上,我想知道是否可以为Android手机完成。

The actual behavior across different devices is inconsistent . 跨不同设备的实际行为是不一致的 The resize and orientationChange events can fire in a different sequence with varying frequency. resize和orientationChange事件可以以不同的频率以不同的顺序触发。 Also, some values (eg screen.width and window.orientation) don't always change when you expect. 此外,某些值(例如screen.width和window.orientation)并不总是在您预期时更改。 Avoid screen.width -- it doesn't change when rotating in iOS. 避免使用screen.width - 在iOS中旋转时不会改变。

The reliable approach is to listen to both resize and orientationChange events (with some polling as a safety catch), and you'll eventually get a valid value for the orientation. 可靠的方法是监听resize和orientationChange事件 (将一些轮询作为安全捕获),并且最终将获得有效的方向值。 In my testing, Android devices occasionally fail to fire events when rotating a full 180 degrees, so I've also included a setInterval to poll the orientation. 在我的测试中,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);

Here are the results from the four devices that I've tested (sorry for the ASCII table, but it seemed like the easiest way to present the results). 以下是我测试的四个设备的结果(对于ASCII表感到遗憾,但它似乎是呈现结果的最简单方法)。 Aside from the consistency between the iOS devices, there is a lot of variety across devices. 除了iOS设备之间的一致性之外,各种设备之间存在很多种类。 NOTE: The events are listed in the order that they fired. 注意:事件按其触发的顺序列出。

|==============================================================================|
|     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          |
|----------------+-------------------+-------------+------------+--------------|
| Samsung Galaxy | orientationchange | 0           | 400        | 400          |
| Tablet         | orientationchange | 90          | 400        | 400          |
| (to landscape) | orientationchange | 90          | 400        | 400          |
|                | resize            | 90          | 683        | 683          |
|                | orientationchange | 90          | 683        | 683          |
|----------------+-------------------+-------------+------------+--------------|
| Samsung Galaxy | orientationchange | 90          | 683        | 683          |
| Tablet         | orientationchange | 0           | 683        | 683          |
| (to portrait)  | orientationchange | 0           | 683        | 683          |
|                | resize            | 0           | 400        | 400          |
|                | orientationchange | 0           | 400        | 400          |
|----------------+-------------------+-------------+------------+--------------|

To detect an orientation change on an Android browser, attach a listener to the orientationchange or resize event on window : 要在Android浏览器上检测方向更改,请将侦听器附加到window上的orientationchangeresize事件:

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

Check the window.orientation property to figure out which way the device is oriented. 检查window.orientation属性以确定设备的方向。 With Android phones, screen.width or screen.height also updates as the device is rotated. 使用Android手机时, screen.widthscreen.height也会随着设备的旋转而更新。 (this is not the case with the iPhone). (这不是iPhone的情况)。

two-bit-fool's excellent answer provides all the background, but let me attempt a concise, pragmatic summary of how to handle orientation changes across iOS and Android : 两位傻瓜的优秀答案提供了所有背景,但让我尝试一下简明实用的总结,介绍如何在iOS和Android上处理方向变化

  • If you only care about window dimensions (the typical scenario) - and not about the specific orientation: 如果您只关心窗口尺寸 (典型情况) - 而不是特定方向:
    • Handle the resize event only. 仅处理resize事件。
    • In your handler, act on window.innerWidth and window.InnerHeight only. 在处理程序中,仅对window.innerWidthwindow.InnerHeight
    • Do NOT use window.orientation - it won't be current on iOS. 不要使用window.orientation - 它不会是最新的iOS。
  • If you DO care about the specific orientation : 如果您关心具体方向
    • Handle only the resize event on Android, and only the orientationchange event on iOS. 处理Android上的resize事件, 处理iOS上的orientationchange事件。
    • In your handler, act on window.orientation (and window.innerWidth and window.InnerHeight ) 在你的处理程序中,作用于window.orientation (和window.innerWidthwindow.InnerHeight

These approaches offer slight benefits over remembering the previous orientation and comparing: 这些方法比记住以前的方向和比较提供了一些好处:

  • the dimensions-only approach also works while developing on desktop browsers that can otherwise simulate mobile devices, eg, Chrome 23. ( window.orientation is not available on desktop browsers). 仅在尺寸方法上也可以在桌面浏览器上进行开发,否则可以模拟移动设备,例如Chrome 23.(桌面浏览器上不提供window.orientation )。
  • no need for a global/anonymous-file-level-function-wrapper-level variable. 不需要全局/匿名文件级函数包装级变量。

You could always listen to the window resize event. 您可以随时收听窗口调整大小事件。 If, on that event, the window went from being taller than it is wide to wider than it is tall (or vice versa), you can be pretty sure the phone orientation was just changed. 如果,在那个事件中,窗口从高宽度变宽到宽度高(反之亦然),你可以非常确定手机方向刚刚改变。

I had the same problem. 我有同样的问题。 I am using Phonegap and Jquery mobile, for Adroid devices. 我正在使用Phonegap和Jquery移动设备,用于Adroid设备。 To resize properly I had to set a timeout: 要正确调整大小,我必须设置超时:

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

It is possible in HTML5. 它可以在HTML5中使用。
You can read more (and try a live demo) here: http://slides.html5rocks.com/#slide-orientation . 您可以在此处阅读更多内容(并尝试现场演示): http//slides.html5rocks.com/#slide-orientation

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

It also supports deskop browsers but it will always return the same value. 它还支持deskop浏览器,但它总是返回相同的值。

Here is the solution: 这是解决方案:

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

you can try the solution, compatible with all browser. 您可以尝试解决方案,与所有浏览器兼容。

Following is orientationchange compatibility pic: 以下是orientationchange兼容性pic: 兼容性 therefore, I author a orientaionchange polyfill, it is a based on @media attribute to fix orientationchange utility library—— orientationchange-fix 因此,我创作了一个orientaionchange ,它基于@media属性来修复orientationchange实用程序库 - orientationchange-fix

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

另一个问题 - 一些Android平板电脑(摩托罗拉Xoom我相信和一个低端的Elonex我正在进行一些测试,可能还有其他一些)安装了加速度计,以便在LANDSCAPE模式下window.orientation == 0,而不是肖像!

Cross browser way 跨浏览器方式

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

值得注意的是,在我的Epic 4G Touch上,我必须设置webview以在任何javascript android调用工作之前使用WebChromeClient。

webView.setWebChromeClient(new WebChromeClient());

A little contribution to the two-bit-fool's answer: 这个两位傻瓜的回答有点贡献:

As described on the table on droid phones "orientationchange" event gets fired earlier than "resize" event thus blocking the next resize call (because of the if statement). 正如droid手机上的表所述,“orientationchange”事件比“resize”事件更早被触发,因此阻止了下一次调整大小调用(因为if语句)。 Width property is still not set. 宽度属性仍未设置。

A workaround though maybe not a perfect one could be to not fire the "orientationchange" event. 一个解决方法虽然可能不是一个完美的可能是不会触发“orientationchange”事件。 That can be archived by wrapping "orientationchange" event binding in "if" statement: 这可以通过在“if”语句中包装“orientationchange”事件绑定来存档:

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

Hope it helps 希望能帮助到你

(tests were done on Nexus S) (在Nexus S上进行了测试)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM