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

我发现这个方向测试代码下面寻找 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;
}
}
254672 次浏览

我对 iOS 和 Phonegap 也很陌生,但是我可以通过添加一个 Event Listener 来做到这一点。我做了同样的事情(使用您引用的示例) ,但是无法让它工作。但这似乎奏效了:

// 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 谷歌集团 “迎新会”这个词

我读过的一个关于如何检测方向的例子是 Pie Guy: (游戏Js 文件)。和你发布的代码很像,但和你一样,我无法让它工作。

需要注意的是: Event Listener 对我有用,但是我不确定这是否是一种过度集中的方法。到目前为止,这是唯一适合我的方法,但我不知道是否有更好的,更流线型的方法。


UPDATE 修复了上面的代码,现在可以工作了

我正在为 iPhone 在 PhoneGap 中创建一个 jQTouch 应用程序。这个问题我已经纠结好几天了。我已经看到事件侦听器解决方案建议了几次,但就是不能让它工作。

最后我想出了一个不同的解决办法。它基本上使用 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!');
}

我用 window.onresize = function(){ checkOrientation(); } 并且在 check旋转方向中,你可以使用 windows. 旋转方向或者身体宽度检查 但是这个想法是,“ window.onresize”是最跨浏览器的方法,至少对于我有机会测试过的大多数移动和桌面浏览器来说是这样。

这就是我的工作:

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


更新于2019年5月: window.orientation是一个不受欢迎的特性,大多数浏览器 根据 MDN都不支持。orientationchange事件是 与 windows 方向相关联,因此可能不应该使用。

以下几点对我很有效:

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的值不会马上更新

在处理 orientationchange事件时,我需要一个超时来获得页面中元素的正确尺寸,但 match Media 工作得很好。我的终极准则:

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

我发现这个代码可以检测设备是否处于横向位置,在这个例子中,添加一个醒目页面,上面写着“更改方向以查看站点”。它正在 iOS,android 和 windows 手机上运行。我认为这是非常有用的,因为它是相当优雅的,避免为移动站点设置一个横向视图。 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>

还有 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.matchMedia("(orientation: portrait)").matches) {
// you're in PORTRAIT mode
}


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

我是这么做的:

window.addEventListener('orientationchange', doOnOrientationChange);


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

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

在某些平台上,各种属性(如窗口尺寸(window.innerWidthwindow.innerHeight)和 window.orientation属性)在事件 "orientationchange"触发时不会更新。很多时候,属性 window.orientation在启动 "orientationchange"后的几毫秒内是 undefined(至少在 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);

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

现在,我将为此创建一个 JSFiddle,就像我通常做的那样,但是 JSFiddle 并没有为我工作,而且我对它的支持 bug 已经关闭了,因为没有其他人报告相同的问题。如果还有人想把这个变成 JSFiddle 请便。

谢谢! 我希望这有帮助!

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

虽然这个问题只涉及到 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之前触发,所以除非在方向更改事件之后添加一些延迟,否则不会得到屏幕的实际尺寸。

  3. 有一个 屏幕定位插件支持老式的移动浏览器,但我认为现在没有必要使用它。

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

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

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