JavaScriptを使用してブラウザーでAndroidフォンの回転を検出する


187

iPhoneのSafariでは、onorientationchangeイベントをリッスンwindow.orientationして角度を問い合わせることで、画面の向きと向きの変化を検出できることを知っています。

これはAndroidフォンのブラウザで可能ですか?

明確にするために、Androidデバイスの回転が標準のWebページで実行されているJavaScriptによって検出できるかどうかを尋ねています。iPhoneでも可能ですが、Android携帯でできるのかと思いました。

回答:


214

Androidのブラウザでの姿勢変化を検出するために、にリスナーを添付するorientationchangeか、resize上のイベントwindow

// Detect whether device supports orientationchange event, otherwise fall back to
// the resize event.
var supportsOrientationChange = "onorientationchange" in window,
    orientationEvent = supportsOrientationChange ? "orientationchange" : "resize";

window.addEventListener(orientationEvent, function() {
    alert('HOLY ROTATING SCREENS BATMAN:' + window.orientation + " " + screen.width);
}, false);

window.orientationプロパティを確認して、デバイスの向きを確認してください。Androidスマートフォンの場合、screen.widthまたはscreen.heightデバイスの回転に合わせて更新されます。(これはiPhoneには当てはまりません)。


これは本当に機能しますか?私はjquery $(window).bind( "orientationchange"、fn);を試しました。うまくいきませんでした。上のフォームを使用する必要がありますか?ウィンドウで「onorientationchange」を試しましたが、falseに戻ります
Ayyash

それはうまくいきます。Ayyash-「orientationchange」がサポートされていない場合、「リサイズ」にフォールバックするという重要なポイント
Dror

9
ドロイドではこれは完全に正気ではない。携帯電話を横向きモードで回転させるとscreen.widthに320のアラートが表示され、縦向きモードで回転させるとscreen.width 569が検出されます。どうして??
IgorGanapolsky

1
明確にするために:iOSでも機能するソリューションを探している人は、2ビットの愚か者か私の答えを見る必要があります。
mklement0

3
iOSで2ビットフールのハックを使用する必要はありません。AndroidとiOSではscreen.widthとscreen.heightを使用し、window.innerWidthとwindow.innerHeightを使用します。
ジャスティン

224

異なるデバイス間での実際の動作は一貫していません。resizeイベントとorientationChangeイベントは、さまざまな頻度で異なるシーケンスで発生する可能性があります。また、一部の値(screen.widthやwindow.orientationなど)は、期待どおりに常に変化するとは限りません。screen.widthは避けてください-iOSで回転しても変わりません。

信頼できるアプローチは、リサイズイベントとorientationChangeイベントの両方をリッスンすることです(安全のためにいくつかのポーリングを行います)。最終的には、向きの有効な値を取得します。私のテストでは、Androidデバイスが180度完全に回転したときにイベントの起動に失敗することがあるので、方向をポーリングするsetIntervalも含めました。

var previousOrientation = window.orientation;
var checkOrientation = function(){
    if(window.orientation !== previousOrientation){
        previousOrientation = window.orientation;
        // orientation changed, do your magic here
    }
};

window.addEventListener("resize", checkOrientation, false);
window.addEventListener("orientationchange", checkOrientation, false);

// (optional) Android doesn't always fire orientationChange on 180 degree turns
setInterval(checkOrientation, 2000);

これは私がテストした4つのデバイスからの結果です(ASCIIテーブルでは申し訳ありませんが、結果を表示する最も簡単な方法のように思われました)。iOSデバイス間の一貫性は別として、デバイス間で多くの多様性があります。注:イベントは、発生した順序で一覧表示されます。

| ================================================= ============================= |
| デバイス| 発生したイベント| オリエンテーション| innerWidth | screen.width |
| ================================================= ============================= |
| iPad 2 | サイズ変更| 0 | 1024 | 768 |
| (横向き)| オリエンテーションチェンジ| 90 | 1024 | 768 |
| ---------------- + ------------------- + ------------ -+ ------------ + -------------- |
| iPad 2 | サイズ変更| 90 | 768 | 768 |
| (ポートレートへ)| オリエンテーションチェンジ| 0 | 768 | 768 |
| ---------------- + ------------------- + ------------ -+ ------------ + -------------- |
| iPhone 4 | サイズ変更| 0 | 480 | 320 |
| (横向き)| オリエンテーションチェンジ| 90 | 480 | 320 |
| ---------------- + ------------------- + ------------ -+ ------------ + -------------- |
| iPhone 4 | サイズ変更| 90 | 320 | 320 |
| (ポートレートへ)| オリエンテーションチェンジ| 0 | 320 | 320 |
| ---------------- + ------------------- + ------------ -+ ------------ + -------------- |
| ドロイドフォン| オリエンテーションチェンジ| 90 | 320 | 320 |
| (横向き)| サイズ変更| 90 | 569 | 569 |
| ---------------- + ------------------- + ------------ -+ ------------ + -------------- |
| ドロイドフォン| 方向変更| 0 | 569 | 569 |
| (ポートレートへ)| サイズ変更| 0 | 320 | 320 |
| ---------------- + ------------------- + ------------ -+ ------------ + -------------- |
| Samsung Galaxy | オリエンテーションチェンジ| 0 | 400 | 400 |
| タブレット| オリエンテーションチェンジ| 90 | 400 | 400 |
| (横向き)| オリエンテーションチェンジ| 90 | 400 | 400 |
| | サイズ変更| 90 | 683 | 683 |
| | オリエンテーションチェンジ| 90 | 683 | 683 |
| ---------------- + ------------------- + ------------ -+ ------------ + -------------- |
| Samsung Galaxy | オリエンテーションチェンジ| 90 | 683 | 683 |
| タブレット| オリエンテーションチェンジ| 0 | 683 | 683 |
| (ポートレートへ)| オリエンテーションチェンジ| 0 | 683 | 683 |
| | サイズ変更| 0 | 400 | 400 |
| | オリエンテーションチェンジ| 0 | 400 | 400 |
| ---------------- + ------------------- + ------------ -+ ------------ + -------------- |

iOS5エミュレーターで、横向きに更新して回転すると、このコードは起動しません。
勤務

1
すばらしい答えです。そのときのpreviousOrientation現在の向きで初期化する必要がありますvar previousOrientation = window.orientation;。180度の回転を無視する場合、つまり、左または右のランドスケープと上下逆または無のバリエーションを区別する必要がない場合は、次を追加します。の最初の行としてcheckOrientation()if (0 === (previousOrientation + window.orientation) % 180) return;ただし、追加のsetTimeoutトリックを行わなくても、180度の高速回転で1 つの orientationchangeイベントしか作成されないiOSでのみ、このメリットが得られます。
mklement0

@mklementに感謝し、previousOrientationを初期化するようにコードを微調整しました。
2ビットフール

すばらしい情報をありがとう。コルドバを使用するとき、Windows Phone 8.1はサイズ変更または方向変更イベントを備えていないので、これは私の頭の中にありました。setIntervalおよびフェイルセーフを使用するように頼りました。
完璧

@ mklement0今日まで、Windows Phone 8.1ではwindow.orientationは常に未定義です。
完成

39

two-bit-foolの優れた答えはすべての背景を提供しますが、iOSとAndroid間の向きの変更を処理する方法の簡潔で実用的な要約を試してみましょう:

  • 特定の方向ではなくウィンドウの寸法(一般的なシナリオ)のみに関心がある場合
    • resizeイベントのみを処理します。
    • ハンドラーではwindow.innerWidthwindow.InnerHeightただ行動するだけです。
    • 使用しないでください-iOSではwindow.orientation最新ではありません。
  • 特定の向きに関心がある場合
    • ハンドルのみresizeのAndroid上のイベント、そして唯一orientationchangeのiOS上のイベントを。
    • ハンドラで、window.orientation(およびwindow.innerWidthおよびwindow.InnerHeight)に基づいて動作します

これらのアプローチには、以前の向きを覚えて比較するよりもわずかな利点があります。

  • ディメンションのみのアプローチは、Chrome 23などのモバイルデバイスをシミュレートできるデスクトップブラウザーでの開発中にも機能します(デスクトップブラウザーでwindow.orientationは使用できません)。
  • グローバル/匿名ファイルレベル関数ラッパーレベル変数は必要ありません。

問題は、サイズ変更または方向付けイベントがwindow.innerWidthを発火すると、Droidデバイスが誤って報告されることです
albanx

@albanxはまだiosのChromeの問題です:/ safariは問題あり
ません

12

いつでもウィンドウのサイズ変更イベントをリッスンできます。そのイベントで、ウィンドウの幅が高さから高さ(またはその逆)に変わった場合、電話の向きが変更されただけであることがかなりわかります。


それは良い考えです。私はそれを試してみます(そしてAndroidフォンを持っている私の友人にテストを依頼してください!)
philnash '30 / 10/30

この方法では電話の向きがわかりません。縦向きか横向きかはわかりますが、上下を逆にしたり、左右を向いたりした場合はわかりません。さらなるアイデアは?
philnash 2009年

どうしてそれが問題になるのかわからない...電話が逆さまになっているかどうかを知る必要があるのはなぜですか。電話のブラウザには上部があり、Webページはブラウザの上部に向けられます。2つの脳細胞をこすり合わせてWebページを上下逆に見ているユーザーは、携帯電話を裏返しにして見たい場合は、携帯電話をひっくり返すだけです
Joel Mueller

1
それは少し厳しいです。画面の向きに基づいてさまざまなコンテンツを表示できるようにしたいと思います。これは最大4つの異なるページになる可能性があり、ブラウザが0、90、180、270度回転したかどうかをブラウザに知らせる必要があります。これはJavaScript、iPhoneですべて可能であり、私が求めているのはこのためです。
philnash 2009年

それでも、レンダリングされたデバイスが270度回転されたときにWebページが異なる方法でどのように役立つかを描写するのに苦労していますが、有効なユースケースがあると言えば、私は疑いません。その場合:すみませんが、Androidブラウザーがこのレベルの詳細を提供しているかどうかはわかりません。
Joel Mueller、

3

HTML5で可能です。
詳しくは、http//slides.html5rocks.com/#slide-orientationをご覧ください(そしてライブデモをお試しください)

window.addEventListener('deviceorientation', function(event) {
    var a = event.alpha;
    var b = event.beta;
    var g = event.gamma;
}, false);

また、deskopブラウザもサポートしていますが、常に同じ値を返します。


4
このイベントはモーションセンサーにアクセスするためのものですが、方向の変化を検出するためにも使用できると思います。
ルネ・

私のAndroid Galaxy S2では、ストックブラウザーやDolphinブラウザーではサポートされていません。ただし、モバイルFirefoxで正常に動作します。
Eduardo

3

私も同じ問題を抱えていました。Adroidデバイス用にPhonegapとJqueryモバイルを使用しています。適切にサイズ変更するには、タイムアウトを設定する必要がありました。

$(window).bind('orientationchange',function(e) {
  fixOrientation();
});

$(window).bind('resize',function(e) {
  fixOrientation();
});

function fixOrientation() {

    setTimeout(function() {

        var windowWidth = window.innerWidth;

        $('div[data-role="page"]').width(windowWidth);
        $('div[data-role="header"]').width(windowWidth);
        $('div[data-role="content"]').width(windowWidth-30);
        $('div[data-role="footer"]').width(windowWidth);

    },500);
}

2

これが解決策です:

var isMobile = {
    Android: function() {
        return /Android/i.test(navigator.userAgent);
    },
    iOS: function() {
        return /iPhone|iPad|iPod/i.test(navigator.userAgent);
    }
};
if(isMobile.Android())
    {
        var previousWidth=$(window).width();
        $(window).on({
        resize: function(e) {
        var YourFunction=(function(){

            var screenWidth=$(window).width();
            if(previousWidth!=screenWidth)
            {
                previousWidth=screenWidth;
                alert("oreientation changed");
            }

        })();

        }
    });

    }
    else//mainly for ios
    {
        $(window).on({
            orientationchange: function(e) {
               alert("orientation changed");
            }   
        });
    }

これは私にとって最も効果的な解決策です。100%正確ではないことはわかっていますが、これを使用して水平と垂直を検出できます。varscreenWidth = $(window).width(); var screenHeight = $(window).height(); if(screenWidth> screenHeight){doSomething(); }
math0ne

これは私にとって、安っぽいAndroidタブレットでの解決策でした。window.onresize、attachevent、addeventlistenerが複数のイベント(サイズ変更、サイズ変更、方向変更、デバイス方向)で失敗しました。Jquery $(window).on()のみが機能しました。
Lego

1

別の落とし穴-一部のAndroidタブレット(私が信じているMotorola Xoomと私がいくつかのテストを行っているローエンドのElonexタブレット、おそらく他のものも)は、ポートレートではなく、ランドスケープモードでwindow.orientation == 0になるように加速度計を設定しています!


1

すべてのブラウザと互換性のあるソリューションを試すことができます。

以下はorientationchange互換性の写真です: 互換性 したがって、私はorientaionchangeポリフィルを作成します。これは@media属性に基づいており、orientationchangeユーティリティライブラリを修正します——orientationchange -fix

window.addEventListener('orientationchange', function(){
 if(window.neworientation.current === 'portrait|landscape'){
    // do something……
 } else {
    // do something……
 }
}, false);

0

私のEpic 4G Touchでは、javascript android呼び出しが機能する前に、WebChromeClientを使用するようにwebviewを設定する必要があったことに注目する価値があります。

webView.setWebChromeClient(new WebChromeClient());

0

クロスブラウザーの方法

$(window).on('resize orientationchange webkitfullscreenchange mozfullscreenchange fullscreenchange',  function(){
//code here
});

-1

2ビットフールの答えへの少しの貢献:

ドロイド電話の表に記載されているように、「orientationchange」イベントは「resize」イベントよりも早く発生するため、次のサイズ変更呼び出しがブロックされます(ifステートメントのため)。Widthプロパティはまだ設定されていません。

完全ではないかもしれませんが、回避策は "orientationchange"イベントを発生させないことです。これは、 "if"ステートメントで "orientationchange"イベントバインディングをラップすることでアーカイブできます。

if (!navigator.userAgent.match(/android/i))
{
    window.addEventListener("orientationchange", checkOrientation, false);
}

それが役に立てば幸い

(テストはNexus Sで行われました)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.