iPhone と Android の onOrientationChange タイミングの違い

またスマートフォン対応サイトネタ、Androidネタです。

Androidのブラウザにて。Android 2.2から、iPhoneと同じように縦持ち・横持ちが変わった際に発生するイベント「window.onorientationchange」が使えるようになっているようです。ですが、このイベントが起きるタイミングがiPhoneAndroidで異なっているようです。

var $win = $(window);
var debug = $('#debug');
$win.bind( 'orientationchange', function() {
    debug.html( debug.html() + 'orient:' + $win.width() + ', ' );
} )
.bind( 'resize', function(){
    debug.html( debug.html() + 'resize:' + $win.width() + ', ' );
} );

上のJavaScriptを実行すると、iPhoneの場合は、

  • ウィンドウのサイズ変更 → resizeイベント → orientationchangeイベント

という順番でイベントが発生していることがわかります(なんだか、resizeイベントが2回発生するケースもあるみたい)。

ところが Android 2.2の場合は、

  • orientationchangeイベント → ウィンドウのサイズ変更 → resizeイベント

という順番になります。

ちなみに、Android 2.1以前は、typeof window.onorientationchange === 'undefined' なので、

  • ウィンドウサイズの変更 → resizeイベント

となっています。

orientationchangeイベントだけだと、iPhoneの場合は変更後の、Androidの場合は変更前の値を持ってきてしまうことになりますので、ウィンドウサイズを元に表示を変更しようとした場合にはおかしなことになってしまいます。以下のように判定をしている場合には、注意が必要ですね。

if ( typeof window.onorientationchange === 'object' ) {
     $(window).bind( 'orientationchange', function(){ hoge(); } );
} else {
     $(window).bind( 'resize', function(){ hoge(); } );
}

Androidの場合には、resizeイベントを使うようにすると、iPhoneと共通化ができると思います。

var isAndroid = navigator.userAgent.indexOf('Android') != -1;
if ( typeof window.onorientationchange === 'object' && ! isAndroid ) {
     $(window).bind( 'orientationchange', function(){ hoge(); } );
} else {
     $(window).bind( 'resize', function(){ hoge(); } );
}

ちなみにAndroidのresizeイベントは、アドレスバーが表示されている間はスクロールするだけで発生するようなので、重い処理はさせないほうが良さそうです。