Обнаружение вращения телефона Android в браузере с помощью JavaScript

Я знаю, что в Safari на iPhone вы можете обнаружить ориентацию экрана и изменение ориентации, прослушивая onorientationchange событие и запрос window.orientation для угла.

Возможно ли это в браузере на телефонах Android?

Чтобы было ясно, я спрашиваю, можно ли обнаружить вращение устройства Android с помощью JavaScript, работающего на стандартной веб-странице. Это возможно на iPhone, и мне было интересно, можно ли это сделать для телефонов Android.

12 ответов

Решение

Чтобы обнаружить изменение ориентации в браузере 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).

Фактическое поведение на разных устройствах противоречиво. События resize и directionChange могут запускаться в различной последовательности с различной частотой. Кроме того, некоторые значения (например, screen.width и window.orientation) не всегда меняются, когда вы ожидаете. Избегайте screen.width - он не меняется при повороте в iOS.

Надежный подход заключается в прослушивании как resize, так и directionChange событий (с некоторым опросом в качестве предохранителя), и вы в конечном итоге получите действительное значение для ориентации. В моем тестировании 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);

Вот результаты четырех устройств, которые я тестировал (извините за таблицу 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          |
|----------------+-------------------+-------------+------------+--------------|

Отличный ответ two-bit-fool обеспечивает весь фон, но позвольте мне попробовать краткое, прагматичное резюме того, как обрабатывать изменения ориентации в iOS и Android:

  • Если вам важны только размеры окна (типичный сценарий), а не конкретная ориентация:
    • Обрабатывать resize только событие
    • В вашем обработчике действуйте на window.innerWidth а также window.InnerHeight только.
    • Не использовать window.orientation - это не будет актуальным на iOS.
  • Если вы действительно заботитесь о конкретной ориентации:
    • Обрабатывать только resize событие на Android, и только orientationchange событие на iOS.
    • В вашем обработчике действуйте на window.orientation (а также window.innerWidth а также window.InnerHeight)

Эти подходы предлагают небольшие преимущества по сравнению с запоминанием предыдущей ориентации и сравнением:

  • Подход, основанный только на размерах, также работает при разработке браузеров для настольных компьютеров, которые могут имитировать мобильные устройства, например Chrome 23. (window.orientation недоступно в настольных браузерах).
  • нет необходимости в глобальной / анонимной переменной уровня файла-функции-оболочки-уровня.

Вы всегда можете прослушать событие изменения размера окна. Если в этом случае окно стало не выше, чем широко, то шире, чем высоко (или наоборот), вы можете быть уверены, что ориентация телефона была только что изменена.

Это возможно в HTML5.
Вы можете прочитать больше (и попробовать демо) здесь: http://slides.html5rocks.com/.

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

Он также поддерживает десктопные браузеры, но всегда будет возвращать одно и то же значение.

У меня такая же проблема. Я использую PhoneGap и JQuery для мобильных устройств, для устройств Android. Чтобы правильно изменить размер, я должен был установить таймаут:

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

Вот решение:

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

Вы можете попробовать решение, совместимое со всеми браузерами.

Следующий orientationchange совместимость рис: совместимость поэтому я автор orientaionchange polyfill, он основан на атрибуте @media для исправления библиотеки утилит ориентации—— directionchange -fix

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

Еще одно замечание - на некоторых планшетах Android (я полагаю, Motorola Xoom и бюджетный Elonex, на котором я провожу некоторые испытания, возможно, и на других) установлены акселерометры, так что window.orientation == 0 в режиме LANDSCAPE, а не портрет!

Стоит отметить, что на моем Epic 4G Touch мне пришлось настроить веб-видение для использования WebChromeClient до того, как сработают любые вызовы javascript для Android.

webView.setWebChromeClient(new WebChromeClient());

Кроссбраузерный путь

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

Небольшой вклад в ответ дурачка:

Как описано в таблице на телефонах Droid, событие "directionalchange" запускается раньше, чем событие "resize", таким образом блокируя следующий вызов resize (из-за оператора if). Свойство Width все еще не установлено.

Обходной путь, хотя, возможно, и не идеальный, может заключаться в том, чтобы не запускать событие "directionalchange". Это можно заархивировать, обернув привязку события "directionalchange" в операторе "if":

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

Надеюсь, поможет

(тесты проводились на Nexus S)

Другие вопросы по тегам