简体   繁体   English

如何在 iOS 上使用 Phonegap 正确检测方向变化?

[英]How do I correctly detect orientation change using Phonegap on iOS?

I found this orientation test code below looking for JQTouch reference material.我在下面找到了这个方向测试代码,以寻找 JQTouch 参考资料。 This works correctly in the iOS simulator on mobile Safari but doesn't get handled correctly in Phonegap.这在移动 Safari 上的 iOS 模拟器中可以正常工作,但在 Phonegap 中无法正确处理。 My project is running into the same issue that is killing this test page.我的项目遇到了杀死这个测试页面的同样问题。 Is there a way to sense the orientation change using JavaScript in Phonegap?有没有办法在 Phonegap 中使用 JavaScript 来感知方向变化?

window.onorientationchange = function() {
  /*window.orientation returns a value that indicates whether iPhone is in portrait mode, landscape mode with the screen turned to the
    left, or landscape mode with the screen turned to the right. */
  var orientation = window.orientation;
  switch (orientation) {
    case 0:
      /* If in portrait mode, sets the body's class attribute to portrait. Consequently, all style definitions matching the body[class="portrait"] declaration
         in the iPhoneOrientation.css file will be selected and used to style "Handling iPhone or iPod touch Orientation Events". */
      document.body.setAttribute("class", "portrait");

      /* Add a descriptive message on "Handling iPhone or iPod touch Orientation Events"  */
      document.getElementById("currentOrientation").innerHTML = "Now in portrait orientation (Home button on the bottom).";
      break;

    case 90:
      /* If in landscape mode with the screen turned to the left, sets the body's class attribute to landscapeLeft. In this case, all style definitions matching the
         body[class="landscapeLeft"] declaration in the iPhoneOrientation.css file will be selected and used to style "Handling iPhone or iPod touch Orientation Events". */
      document.body.setAttribute("class", "landscape");

      document.getElementById("currentOrientation").innerHTML = "Now in landscape orientation and turned to the left (Home button to the right).";
      break;

    case -90:
      /* If in landscape mode with the screen turned to the right, sets the body's class attribute to landscapeRight. Here, all style definitions matching the
         body[class="landscapeRight"] declaration in the iPhoneOrientation.css file will be selected and used to style "Handling iPhone or iPod touch Orientation Events". */
      document.body.setAttribute("class", "landscape");

      document.getElementById("currentOrientation").innerHTML = "Now in landscape orientation and turned to the right (Home button to the left).";
      break;
  }
}

This is what I do:这就是我所做的:

 function doOnOrientationChange() { switch(window.orientation) { case -90: case 90: alert('landscape'); break; default: alert('portrait'); break; } } window.addEventListener('orientationchange', doOnOrientationChange); // Initial execution if needed doOnOrientationChange();


Update May 2019: window.orientation is a deprecated feature and not supported by most browsers according to MDN . 2019 年 5 月更新: window.orientation是一项已弃用的功能, 根据 MDN ,大多数浏览器都不支持。 The orientationchange event is associated with window.orientation and therefore should probably not be used. orientationchange事件与 window.orientation 相关联,因此可能不应该使用。

I use window.onresize = function(){ checkOrientation(); }我使用window.onresize = function(){ checkOrientation(); } window.onresize = function(){ checkOrientation(); } And in checkOrientation you can employ window.orientation or body width checking but the idea is, the "window.onresize" is the most cross browser method, at least with the majority of the mobile and desktop browsers that I've had an opportunity to test with. window.onresize = function(){ checkOrientation(); }而在checkOrientation你可以聘请window.orientation或车身宽度检查,但这个想法是,在“window.onresize”是最跨浏览器的方法,至少与广大的移动和桌面浏览器,我已经有机会测试。

if (window.matchMedia("(orientation: portrait)").matches) {
   // you're in PORTRAIT mode
}

if (window.matchMedia("(orientation: landscape)").matches) {
  // you're in LANDSCAPE mode
}

I'm pretty new to iOS and Phonegap as well, but I was able to do this by adding in an eventListener.我对 iOS 和 Phonegap 也很陌生,但我能够通过添加一个 eventListener 来做到这一点。 I did the same thing (using the example you reference), and couldn't get it to work.我做了同样的事情(使用您引用的示例),但无法使其正常工作。 But this seemed to do the trick:但这似乎奏效了:

// Event listener to determine change (horizontal/portrait)
window.addEventListener("orientationchange", updateOrientation); 

function updateOrientation(e) {
switch (e.orientation)
{   
    case 0:
        // Do your thing
        break;

    case -90:
        // Do your thing
        break;

    case 90:
        // Do your thing
        break;

    default:
        break;
    }
}

You may have some luck searching the PhoneGap Google Group for the term "orientation" .您可能会在 PhoneGap Google Group 中搜索“orientation”这个词

One example I read about as an example on how to detect orientation was Pie Guy: ( game , js file ).我读到的一个关于如何检测方向的例子是 Pie Guy: ( game , js file )。 It's similar to the code you've posted, but like you... I couldn't get it to work.它类似于您发布的代码,但就像您一样......我无法让它工作。

One caveat: the eventListener worked for me, but I'm not sure if this is an overly intensive approach.一个警告: eventListener 为我工作,但我不确定这是否是一种过于密集的方法。 So far it's been the only way that's worked for me, but I don't know if there are better, more streamlined ways.到目前为止,这是对我有用的唯一方法,但我不知道是否有更好、更简化的方法。


UPDATE fixed the code above, it works now UPDATE修复了上面的代码,现在可以使用了

Although the question refers to only PhoneGap and iOS usage, and although it was already answered, I can add a few points to the broader question of detecting screen orientation with JS in 2019:虽然这个问题只涉及 PhoneGap 和 iOS 的使用,虽然已经有人回答了,但我可以对 2019 年用 JS 检测屏幕方向这个更广泛的问题补充几点:

  1. window.orientation property is deprecated and not supported by Android browsers .There is a newer property that provides more information about the orientation - screen.orientation . window.orientation属性已弃用, Android 浏览器不支持。有一个较新的属性可提供有关方向的更多信息 - screen.orientation But it is still experimental and not supported by iOS Safari .但它仍然是实验性的,不受iOS Safari支持。 So to achieve the best result you probably need to use the combination of the two: const angle = screen.orientation ? screen.orientation.angle : window.orientation因此,为了获得最佳结果,您可能需要结合使用两者: const angle = screen.orientation ? screen.orientation.angle : window.orientation const angle = screen.orientation ? screen.orientation.angle : window.orientation . const angle = screen.orientation ? screen.orientation.angle : window.orientation

  2. As @benallansmith mentioned in his comment , window.onorientationchange event is fired before window.onresize , so you won't get the actual dimensions of the screen unless you add some delay after the orientationchange event.正如@benallansmith 在他的评论中提到的, window.onorientationchange事件在window.onresize之前被触发,因此除非在orientationchange 事件之后添加一些延迟,否则您将无法获得屏幕的实际尺寸。

  3. There is a Cordova Screen Orientation Plugin for supporting older mobile browsers, but I believe there is no need in using it nowadays.有一个Cordova Screen Orientation Plugin用于支持旧的移动浏览器,但我相信现在没有必要使用它。

  4. There was also a screen.onorientationchange event, but it is deprecated and should not be used.还有一个screen.onorientationchange事件,但它已被弃用,不应使用。 Added just for completeness of the answer.添加只是为了答案的完整性。

In my use-case, I didn't care much about the actual orientation, but rather about the actual width and height of the window, which obviously changes with orientation.在我的用例中,我不太关心实际的方向,而是关心窗口的实际宽度和高度,这显然会随着方向而变化。 So I used resize event to avoid dealing with delays between orientationchange event and actualizing window dimensions:所以我使用resize事件来避免处理orientationchange事件和实现窗口尺寸之间的延迟:

window.addEventListener('resize', () => {
  console.log(`Actual dimensions: ${window.innerWidth}x${window.innerHeight}`);
  console.log(`Actual orientation: ${screen.orientation ? screen.orientation.angle : window.orientation}`);
});

Note 1: I used EcmaScript 6 syntax here, make sure to compile it to ES5 if needed.注 1:我在这里使用了 EcmaScript 6 语法,如果需要,请确保将其编译为 ES5。

Note 2: window.onresize event is also fired when virtual keyboard is toggled , not only when orientation changes.注意 2: window.onresize事件也会在虚拟键盘切换触发,而不仅仅是在方向改变时。

While working with the orientationchange event, I needed a timeout to get the correct dimensions of the elements in the page, but matchMedia worked fine.在处理orientationchange事件时,我需要超时才能获得页面中元素的正确尺寸,但matchMedia 工作正常。 My final code:我的最终代码:

var matchMedia = window.msMatchMedia || window.MozMatchMedia || window.WebkitMatchMedia || window.matchMedia;

if (typeof(matchMedia) !== 'undefined') {
  // use matchMedia function to detect orientationchange
  window.matchMedia('(orientation: portrait)').addListener(function() {
    // your code ...
  });
} else {
  // use orientationchange event with timeout (fires to early)
  $(window).on('orientationchange', function() {
    window.setTimeout(function() {
      // your code ...
    }, 300)
  });
}

I believe that the correct answer has already been posted and accepted, yet there is an issue that I have experienced myself and that some others have mentioned here.我相信正确的答案已经发布并被接受,但是我自己也遇到过一个问题,其他一些人也在这里提到过。

On certain platforms, various properties such as window dimensions ( window.innerWidth , window.innerHeight ) and the window.orientation property will not be updated by the time that the event "orientationchange" has fired.在某些平台上,各种属性,如窗口尺寸( window.innerWidthwindow.innerHeight )和window.orientation属性在事件"orientationchange"触发时不会更新。 Many times, the property window.orientation is undefined for a few milliseconds after the firing of "orientationchange" (at least it is in Chrome on iOS).很多时候,属性window.orientation"orientationchange"触发后的几毫秒内是undefined的(至少在 iOS 的 Chrome 中是这样)。

The best way that I found to handle this issue was:我发现处理此问题的最佳方法是:

var handleOrientationChange = (function() {
    var struct = function(){
        struct.parse();
    };
    struct.showPortraitView = function(){
        alert("Portrait Orientation: " + window.orientation);
    };
    struct.showLandscapeView = function(){
        alert("Landscape Orientation: " + window.orientation);
    };
    struct.parse = function(){
        switch(window.orientation){
            case 0:
                    //Portrait Orientation
                    this.showPortraitView();
                break;
            default:
                    //Landscape Orientation
                    if(!parseInt(window.orientation) 
                    || window.orientation === this.lastOrientation)
                        setTimeout(this, 10);
                    else
                    {
                        this.lastOrientation = window.orientation;
                        this.showLandscapeView();
                    }
                break;
        }
    };
    struct.lastOrientation = window.orientation;
    return struct;
})();
window.addEventListener("orientationchange", handleOrientationChange, false);

I am checking to see if the orientation is either undefined or if the orientation is equal to the last orientation detected.我正在检查方向是否未定义或方向是否等于检测到的最后一个方向。 If either is true, I wait ten milliseconds and then parse the orientation again.如果任一为真,我等待十毫秒,然后再次解析方向。 If the orientation is a proper value, I call the showXOrientation functions.如果方向是正确的值,我会调用showXOrientation函数。 If the orientation is invalid, I continue to loop my checking function, waiting ten milliseconds each time, until it is valid.如果方向无效,我继续循环我的检查函数,每次等待十毫秒,直到它有效。

Now, I would make a JSFiddle for this, as I usually did, but JSFiddle has not been working for me and my support bug for it was closed as no one else is reporting the same problem.现在,我会像往常一样为此创建一个 JSFiddle,但 JSFiddle 一直没有为我工作,我的支持错误已关闭,因为没有其他人报告同样的问题。 If anyone else wants to turn this into a JSFiddle, please go ahead.如果其他人想把它变成 JSFiddle,请继续。

Thanks!谢谢! I hope this helps!我希望这有帮助!

here is what i did:这是我所做的:

window.addEventListener('orientationchange', doOnOrientationChange);

function doOnOrientationChange()
{
      if (screen.height > screen.width) {
         console.log('portrait');
      } else {
         console.log('landscape');
      }
}

I've found this code to detect if the device is in landscape orientation and in this case add a splash page saying "change orientation to see the site".我发现这个代码可以检测设备是否处于横向,在这种情况下添加一个启动页面,上面写着“改变方向以查看站点”。 It's working on iOS, android and windows phones.它适用于 iOS、Android 和 Windows 手机。 I think that this is very useful since it's quite elegant and avoid to set a landscape view for the mobile site.我认为这非常有用,因为它非常优雅并且避免为移动站点设置横向视图。 The code is working very well.该代码运行良好。 The only thing not completely satisfying is that if someone load the page being in landscape view the splash page doesn't appears.唯一不完全令人满意的是,如果有人在横向视图中加载页面,则不会出现启动页面。

<script>
(function() {
    'use strict';

    var isMobile = {
        Android: function() {
            return navigator.userAgent.match(/Android/i);
        },
        BlackBerry: function() {
            return navigator.userAgent.match(/BlackBerry/i);
        },
        iOS: function() {
            return navigator.userAgent.match(/iPhone|iPad|iPod/i);
        },
        Opera: function() {
            return navigator.userAgent.match(/Opera Mini/i);
        },
        Windows: function() {
            return navigator.userAgent.match(/IEMobile/i);
        },
        any: function() {
            return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Opera() || isMobile.Windows());
        }
    };
    if (isMobile.any()) {
        doOnOrientationChange();
        window.addEventListener('resize', doOnOrientationChange, 'false');
    }

    function doOnOrientationChange() {
        var a = document.getElementById('alert');
        var b = document.body;
        var w = b.offsetWidth;
        var h = b.offsetHeight;
        (w / h > 1) ? (a.className = 'show', b.className = 'full-body') : (a.className = 'hide', b.className = '');
    }
})();
</script>

And the HTML: <div id="alert" class="hide"> <div id="content">This site is not thought to be viewed in landscape mode, please turn your device </div> </div>和 HTML: <div id="alert" class="hide"> <div id="content">This site is not thought to be viewed in landscape mode, please turn your device </div> </div>

if (window.DeviceOrientationEvent) {
    // Listen for orientation changes
    window.addEventListener("orientationchange", orientationChangeHandler);
    function orientationChangeHandler(evt) {
        // Announce the new orientation number
        // alert(screen.orientation);
        // Find matches
        var mql = window.matchMedia("(orientation: portrait)");

        if (mql.matches)  //true
    }
}

The following worked for me:以下对我有用:

function changeOrientation(){
switch(window.orientation) {
case 0: // portrait, home bottom
case 180: // portrait, home top
 alert("portrait H: "+$(window).height()+" W: "+$(window).width());       
 break;
          case -90: // landscape, home left
          case 90: // landscape, home right
        alert("landscape H: "+$(window).height()+" W: "+$(window).width());
            break;
        }
    }

 window.onorientationchange = function() { 
            //Need at least 800 milliseconds
            setTimeout(changeOrientation, 1000);
        }

I needed the timeout because the value of window.orientation does not update right away我需要超时,因为window.orientation的值不会立即更新

I'm creating a jQTouch app in PhoneGap for the iPhone.我正在为 iPhone 在 PhoneGap 中创建一个 jQTouch 应用程序。 I've been battling with this issue for days.几天来我一直在与这个问题作斗争。 I've seen the eventlistener solution suggested a few times, but just could not get it to work.我已经看到几次建议的 eventlistener 解决方案,但就是无法让它工作。

In the end I came up with a different solution.最后我想出了一个不同的解决方案。 It basically checks the width of the body periodically using settimeout.它基本上使用 settimeout 定期检查主体的宽度。 If the width is 320 then the orientation is portrait, if 480 then landscape.如果宽度为 320,则方向为纵向,如果为 480,则为横向。 Then, if the orientation has changed since the last check, it will fire either a portrait stuff function or a landscape stuff function where you can do your thing for each orientation.然后,如果自上次检查以来方向发生了变化,它将触发纵向填充功能或横向填充功能,您可以在其中为每个方向进行操作。

Code (note, I know there is some repetition in the code, just haven't bothered to trim it down yet!):代码(注意,我知道代码中有一些重复,只是还没有理会它!):

// get original orientation based on body width
deviceWidth = $('body').width();
if (deviceWidth == 320) {
    currentOrientation = "portrait";
}
else if (deviceWidth == 480) {
    currentOrientation = "landscape";
}

// fire a function that checks the orientation every x milliseconds
setInterval(checkOrientation, 500);

// check orientation
function checkOrientation() {
    deviceWidth = $('body').width();
    if (deviceWidth == '320') {
        newOrientation = "portrait";
    }
    else if (deviceWidth == '480') {
        newOrientation = "landscape";
    }
    // if orientation changed since last check, fire either the portrait or landscape function
    if (newOrientation != currentOrientation) {
        if (newOrientation == "portrait") {
            changedToPortrait();
        }
        else if (newOrientation == "landscape") {
            changedToLandscape();
        }
        currentOrientation = newOrientation;
    }
}

// landscape stuff
function changedToLandscape() {
    alert('Orientation has changed to Landscape!');
}

// portrait stuff
function changedToPortrait() {
    alert('Orientation has changed to Portrait!');
}

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

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