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

ajp*_*lma 174 javascript iphone jqtouch ios cordova

我在下面找到了这个方向测试代码,寻找JQTouch参考资料.这在移动Safari上的iOS模拟器中正常工作,但在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;
  }
}
Run Code Online (Sandbox Code Playgroud)

Ben*_*uer 288

这就是我做的:

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();
Run Code Online (Sandbox Code Playgroud)

  • 另外,我发现在更改宽度和高度之前会更改orientationchange,因此需要稍微延迟才能使用宽度和高度正确检测方向.为此,我存储当前方向,当检测到更改时,我检查方向的变化,以50ms为增量,最多250ms.一旦发现差异,我就会相应地更新页面.在我的Nexus 5中,它通常会在150ms后检测到宽度与高度的差异. (14认同)
  • 出于兴趣,为什么使用setTimeout Kirk? (11认同)
  • 小心!这是特定于设备的 - 度数是指与设备标准方向的差异.换句话说,如果平板电脑被设计为在风景中使用,那么90意味着它处于纵向模式.作为解决此问题的方法,我首先检查窗口的高度与宽度以存储方向,如果有更改,则使用orientationchange更新它. (10认同)
  • 我做了`window.onorientationchange = function(){setTimeout(functionName,0); };` (9认同)
  • 这是我讨论的唯一解决方案:) +1 (3认同)
  • 我发现这也很有用:函数readDeviceOrientation(){if(Math.abs(window.orientation)=== 90){// Landscape} else {// Portrait}}(http://www.williammalone.com/文章/ HTML5,JavaScript的IOS-方向/) (3认同)
  • `||`在`switch`中不能像这样工作.`-90 || 90`相当于`-90`.你实际上需要使用`case -90:case 90:`. (3认同)
  • 我对[此交叉设备和跨浏览器解决方案](http://pioul.fr/cross-device-cross-browser-portrait-landscape-detection)的纵向和横向检测没有任何问题.`$(window).bind("resize",function(){screenOrientation =($(window).width()> $(window).height())?90:0;});` (2认同)

Rai*_*ine 23

我使用window.onresize = function(){ checkOrientation(); } And在checkOrientation中你可以使用window.orientation或body width检查但是想法是,"window.onresize"是最交叉的浏览器方法,至少对于我已经有的大多数移动和桌面浏览器有机会参加考试.

  • 根本不行,因为当键盘出现时,它将重新调整大小(这不是唯一的情况)。真是太棒了! (2认同)
  • @HellBaby当键盘出现时,函数将被调用,但是,根据您用于方向检测的方法,它将检测到方向未被改变,如window.orientation的情况.所以我仍然支持我的回答. (2认同)

avo*_*ion 12

我对iOS和Phonegap也很陌生,但我可以通过添加eventListener来实现这一点.我做了同样的事情(使用你引用的例子),并且无法使它工作.但这似乎可以解决问题:

// 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

您可能有幸在PhoneGap Google Group中搜索术语"方向".

我读到的关于如何检测方向的一个例子是Pie Guy :( 游戏,js文件).它类似于你发布的代码,但是和你一样......我无法让它发挥作用.

一个警告:eventListener为我工作,但我不确定这是否是一个过于密集的方法.到目前为止,它是唯一对我有用的方式,但我不知道是否有更好,更简化的方法.


UPDATE修复了上面的代码,现在可以使用了


Aly*_*yes 12

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

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


Ale*_*nko 10

虽然这个问题只涉及 PhoneGap 和 iOS 的使用,虽然已经有人回答了,但我可以在 2019 年用 JS 检测屏幕方向这个更广泛的问题补充几点:

  1. window.orientation属性已弃用,Android 浏览器不支持。有一个较新的属性可提供有关方向的更多信息 - screen.orientation。但它仍然是实验性的,不受iOS Safari支持。因此,要获得最佳结果,您可能需要结合使用两者:const angle = screen.orientation ? screen.orientation.angle : window.orientation.

  2. 正如@benallansmith 在他的评论中提到的,window.onorientationchange事件是在之前触发的window.onresize,因此除非在orientationchange 事件之后添加一些延迟,否则您将无法获得屏幕的实际尺寸。

  3. 有一个Cordova Screen Orientation Plugin用于支持旧的移动浏览器,但我相信现在没有必要使用它。

  4. 还有一个screen.onorientationchange事件,但它已被弃用,不应使用。添加只是为了答案的完整性。

在我的用例中,我不太关心实际的方向,而是关心窗口的实际宽度和高度,这显然会随着方向而变化。所以我使用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}`);
});
Run Code Online (Sandbox Code Playgroud)

注 1:我在这里使用了 EcmaScript 6 语法,如果需要,请确保将其编译为 ES5。

注 2:切换虚拟键盘时window.onresize也会触发事件,而不仅仅是在方向更改时。


onc*_*ode 5

在处理orientationchange事件时,我需要超时才能获得页面中元素的正确尺寸,但matchMedia工作正常.我的最终代码:

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)
  });
}
Run Code Online (Sandbox Code Playgroud)


Web*_*rer 5

我相信正确的答案已经发布并被接受,但是我自己也遇到过一个问题,其他一些人也在这里提到过。

在某些平台上,各种属性(例如窗口尺寸 ( window.innerWidth, window.innerHeight) 和window.orientation属性)在事件"orientationchange"触发时不会更新。很多时候,物业window.orientationundefined为点火之后的几毫秒"orientationchange"(至少是在iOS版Chrome)。

我发现处理此问题的最佳方法是:

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);
Run Code Online (Sandbox Code Playgroud)

我正在检查方向是否未定义或方向是否等于检测到的最后一个方向。如果任一为真,我等待十毫秒,然后再次解析方向。如果方向是一个合适的值,我调用showXOrientation函数。如果方向无效,我继续循环我的检查函数,每次等待十毫秒,直到它有效。

现在,我会像往常一样为此创建一个 JSFiddle,但 JSFiddle 一直没有为我工作,我的支持错误已关闭,因为没有其他人报告同样的问题。如果其他人想把它变成 JSFiddle,请继续。

谢谢!我希望这有帮助!