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

时间:2011-03-12 19:26:01

标签: javascript iphone ios cordova jqtouch

我在下面找到了这个方向测试代码,寻找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;
  }
}

12 个答案:

答案 0 :(得分:283)

这就是我的所作所为:

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


更新于2019年5月: window.orientation是不推荐使用的功能,大多数浏览器according to MDN都不支持。 orientationchange事件为associated with window.orientation,因此可能不应使用。

答案 1 :(得分:21)

我使用window.onresize = function(){ checkOrientation(); } 在checkOrientation中,您可以使用window.orientation或body width检查 但想法是,“window.onresize”是最常用的浏览器方法,至少对于我有机会测试的大多数移动和桌面浏览器而言。

答案 2 :(得分:11)

我对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;
    }
}

您可能有幸在PhoneGap Google小组for the term "orientation"中搜索。

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

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


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

答案 3 :(得分:10)

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

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

答案 4 :(得分: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)
  });
}

答案 5 :(得分:2)

这就是我所做的:

window.addEventListener('orientationchange', doOnOrientationChange);

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

答案 6 :(得分:2)

我相信已经发布并接受了正确答案,但我自己也遇到了一个问题,其他一些人已在此提及。

在某些平台上,在事件window.innerWidth具有的时间内,不会更新窗口维度(window.innerHeightwindow.orientation)和"orientationchange"属性等各种属性被解雇。很多时候window.orientation属性undefined"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);

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

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

谢谢!我希望这有帮助!

答案 7 :(得分:1)

我发现此代码可以检测设备是否处于横向方向,并且在这种情况下添加一个“更改方向以查看网站”的启动页面。它适用于iOS,Android和Windows手机。我认为这非常有用,因为它非常优雅,并且避免为移动网站设置横向视图。 代码工作得很好。唯一不能令人满意的是,如果有人在横向视图中加载页面,则不会出现启动页面。

<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>

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>

答案 8 :(得分:0)

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
    }
}

答案 9 :(得分:0)

尽管该问题仅涉及PhoneGap和iOS的使用,尽管已经回答,但我可以在2019年使用JS检测屏幕方向这一更广泛的问题上添加几点:

  1. window.orientation属性is deprecated and not supported by Android browsers。有一个更新的属性,可提供有关方向的更多信息-screen.orientation。但是它仍处于试验阶段, iOS Safari 不支持。因此,要获得最佳结果,您可能需要结合使用以下两项:const angle = screen.orientation ? screen.orientation.angle : window.orientation

  2. 正如his comment中的@benallansmith所说,window.onorientationchange事件在window.onresize之前被触发,因此除非获得一些延迟,否则您将无法获得屏幕的实际尺寸。方向更改事件。

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

  4. 也有一个screen.onorientationchange事件,但是它is deprecated,因此不应使用。添加只是为了完整答案。

在我的用例中,我不太在乎实际的方向,而是在乎窗口的实际宽度和高度,这显然会随着方向而变化。因此,我使用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}`);
});

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

注意2:window.onresize事件也将触发when virtual keyboard is toggled,不仅在方向改变时。

答案 10 :(得分:-1)

以下对我有用:

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

我需要超时,因为window.orientation的值不会立即更新

答案 11 :(得分:-2)

我正在为PhoneGap为iPhone创建一个jQTouch应用程序。几天来我一直在与这个问题作斗争。我已经看过eventlistener解决方案建议了几次,但是无法让它工作。

最后我想出了一个不同的解决方案。它基本上使用settimeout定期检查身体的宽度。如果宽度为320,则方向为纵向,如果480则为横向。然后,如果自上次检查后方向已经改变,它将启动肖像填充功能或横向填充功能,您可以为每个方向执行操作。

代码(注意,我知道代码中有一些重复,只是还没有费心去修剪它!):

// 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!');
}