Виявити обертання телефону Android в браузері за допомогою JavaScript


187

Я знаю, що в Safari на iPhone ви можете виявити орієнтацію екрана та зміну орієнтації, прослуховуючи onorientationchangeподію та запитуючи window.orientationкут.

Чи можливо це в браузері на телефонах Android?

Щоб було зрозуміло, я запитую, чи можна обертати пристрій Android за допомогою 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 ("орієнтаціязміни", fn); але це не спрацювало, чи потрібно використовувати форму вище? Я спробував "onorientationchange" у вікні, він ретушив помилково
Айяш

Це добре працює. Айяш - вся справа в тому, що коли "орієнтаціязміни" не підтримується, вона впаде до "змінити розмір"
Dror,

9
На Droid це абсолютно божевільно. Він попереджає ширину екрана 320, коли телефон повертається в альбомному режимі, і він виявляє ширину екрана 569, коли телефон повертається в портретному режимі! Звідки ??
ІгорГанапольський

1
Тільки для уточнення: Ті, хто шукає рішення, яке також працює на iOS, повинні дивитись на відповідь двох біт-дурня або на мою відповідь.
mklement0

3
Не потрібно використовувати хакінг з двома бітами для iOS. Просто використовуйте screen.width і screen.height на Android і на iOS, використовуйте window.innerWidth і window.innerHeight.
Джастін

224

Фактична поведінка на різних пристроях невідповідна . Події зміни розміру та орієнтаціїChange можуть запускатись в різній послідовності з різною частотою. Також деякі значення (наприклад, ширина екрана та орієнтація вікон) не завжди змінюються, коли ви очікуєте. Уникайте ширини екрана - вона не змінюється при обертанні в iOS.

Надійний підхід полягає в прослуховуванні подій як розміру, так і орієнтації ( ChangeChange) (з деякими опитуваннями як захоплення безпеки), і ви з часом отримаєте дійсне значення для орієнтації. У моєму тестуванні 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, на різних пристроях існує велика різноманітність. ПРИМІТКА. Події перераховані в порядку, в якому вони розпочалися.

| ==================================================== ============================== |
| Пристрій | Розпочаті події | орієнтація | внутрішня ширина | ширина екрана |
| ==================================================== ============================== |
| 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 |
| ---------------- + ------------------- + ------------ - + ------------ + -------------- |
| Droid телефон | зміна орієнтації | 90 | 320 | 320 |
| (до пейзажу) | змінити розмір | 90 | 569 | 569 |
| ---------------- + ------------------- + ------------ - + ------------ + -------------- |
| Droid телефон | зміна орієнтації | 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хитрощів, ви отримаєте користь від цього лише в iOS, де швидке обертання на 180 градусів створює лише одну orientationchange подію.
mklement0

Завдяки @mklement, я підкоригував код, щоб ініціалізувати попередню Орієнтацію.
двійка-дурень

Ура за велику інформацію. Це робилося моєю головою, тому що в телефоні Windows 8.1 немає події зміни розміру чи орієнтації, коли ви використовуєте cordova. Призначено для використання setInterval також як безпечний.
Вдосконалення

@ mklement0 На сьогоднішній день window.orientation завжди буде не визначено на телефоні Windows 8.1.
Досконалість

39

Чудова відповідь двох біт-дурня забезпечує все передумови, але дозвольте спробувати стислий, прагматичний підсумок, як впоратися зі змінами орієнтації в iOS та Android :

  • Якщо ви дбаєте лише про розміри вікон (типовий сценарій) - а не про конкретну орієнтацію:
    • Обробляти лише resizeподію.
    • У своєму обробнику діяти тільки window.innerWidthі window.InnerHeightтільки.
    • НЕ використовуйте window.orientation- це не буде поточним на iOS.
  • Якщо Ви дбаєте про конкретну орієнтацію :
    • Обробляти тільки на resizeподію на Android, і тільки на orientationchangeподію на прошивці.
    • Дійте на window.orientationwindow.innerWidthта window.InnerHeight)

Ці підходи пропонують невелику користь від запам'ятовування попередньої орієнтації та порівняння:

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

Проблема полягає в тому, що при
зміні

@albanx, яка все ще є проблемою в хромуванні на ios: / safari є чудовим
oldboy

12

Ви завжди можете прослухати подію зміни розміру вікна. Якщо в цьому випадку вікно перейшло від високого, ніж широкого до ширшого, ніж високе (або навпаки), ви можете бути впевнені, що орієнтація телефону була просто змінена.


Це гарна ідея, я спробую це (і попросіть свого друга з телефоном Android перевірити!)
philnash

Я щойно зрозумів, що цей метод не дає мені орієнтації телефону. Я буду знати, чи це портрет, чи пейзаж, але ні, якщо він перевернутий ногами або був повернутий ліворуч або праворуч. Будь-які подальші ідеї?
philnash

Я не впевнений, як це могло мати значення ... Навіщо вам знати, чи телефон перевернутий? У браузера телефону є верх, а веб-сторінка буде орієнтована на верхню частину браузера. Будь-який користувач з двома клітинами головного мозку, який потрудить разом, хто дивиться на веб-сторінку догори дном, просто переверне свій телефон, якщо захоче бачити його правою стороною вгору
Джоел Мюллер

1
Це трохи суворо. Мені цікаво знати, щоб я міг показувати різний контент залежно від орієнтації екрана, це може бути до 4 різних сторінок, що вимагає від браузера знати, чи він повертався на 0, 90, 180 та 270 градусів. Це все можливо, в JavaScript, на iPhone, і тому я запитую.
philnash

Я все ще важко уявляю, що веб-сторінка може корисно робити інакше, коли пристрій, на якому вона надається, повертається на 270 градусів, але якщо ви скажете, що у вас є дійсний випадок використання, я не можу посперечатися. У такому випадку: пробачте, але я не маю уявлення, чи забезпечує браузер Android цей рівень деталізації.
Джоель Мюллер

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.
Едуардо

3

У мене була така ж проблема. Я використовую Phonegap та Jquery mobile для пристроїв Adroid. Щоб правильно змінити розмір, мені довелося встановити тайм-аут:

$(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% точне, але ви можете виявити горизонтальну та вертикальну за допомогою цього: var screenWidth = $ (window) .width (); var screenHeight = $ (вікно) .height (); if (screenWidth> screenHeight) {doSomething (); }
math0ne

Це було рішенням для мене на шаленому планшеті Android. window.onresize, attachchevent і addeventlistener не вдалося здійснити декілька подій (зміни розміру, збільшення розміру, зміна орієнтації, орієнтація пристрою). Працював лише Jquery $ (window) .on ().
Лего

1

Ще одна готча - деякі планшети Android (я вважаю, Motorola Xoom, я вважаю, і лоукост Elonex один, на якому я тестую, напевно, і інші), мають свої акселерометри встановлені так, що window.orientation == 0 в режимі LANDSCAPE, а не портрет !


1

ви можете спробувати рішення, сумісне з усіма браузерами.

Далі йде orientationchangeкартина сумісності: сумісність отже, я автор orientaionchangeполіфайли, він заснований на атрибуті @media, щоб виправити орієнтацію змінити бібліотеку утиліт—— orientachange -fix

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

0

Варто зазначити, що на моєму Epic 4G Touch мені довелося налаштувати веб-перегляд, щоб використовувати WebChromeClient до того, як працював будь-який з дзвінків Android для Android.

webView.setWebChromeClient(new WebChromeClient());

0

Перехресний браузерний шлях

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

-1

Невеликий внесок у відповідь двома дурнями:

Як описано в таблиці на дроїдних телефонах подія "орієнтації на зміну" подія запускається раніше, ніж подія "зміни розміру", таким чином блокуючи наступний виклик зміни розміру (через заяву if). Властивість ширини все ще не встановлено.

Хоча рішення, яке, можливо, не є ідеальним, щоб не розпочати подію "зміни орієнтації". Це можна заархівувати, обернувши прив'язку події "орієнтація зміни" в оператор "якщо":

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

Сподіваюся, це допомагає

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.