Wykryj obrót telefonu z Androidem w przeglądarce za pomocą JavaScript

187

Wiem, że w Safari na iPhonie możesz wykryć orientację ekranu i zmianę orientacji, nasłuchując onorientationchangezdarzenia i sprawdzając window.orientationkąt.

Czy jest to możliwe w przeglądarce na telefonach z Androidem?

Dla jasności pytam, czy obrót urządzenia z Androidem można wykryć przez JavaScript działający na standardowej stronie internetowej. Jest to możliwe na iPhonie i zastanawiałem się, czy można to zrobić na telefonach z Androidem.

philnash
źródło

Odpowiedzi:

214

Aby wykryć zmianę orientacji w przeglądarce Androida, dołącz odbiornik do zdarzenia orientationchangelub resizew 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);

Sprawdź window.orientationwłaściwość, aby dowiedzieć się, w którą stronę jest zorientowane urządzenie. Z telefonami z Androidem screen.widthlub screen.heightaktualizuje się wraz z obracaniem urządzenia. (nie jest tak w przypadku iPhone'a).

jb.
źródło
czy to naprawdę działa? próbowałem jquery $ (window) .bind ("orientacja wymiany", fn); ale to nie zadziałało, czy muszę użyć powyższego formularza? Próbowałem "onorientationchange" w okienku, to retuns fałszywy
Ayyash
To dobrze działa. Ayyash - cały punkt tutaj, że gdy „zmiana orientacji” nie jest obsługiwana, wróci do „zmiany rozmiaru”
Dror
9
Na Droidie jest to całkowicie szalone. Ostrzega ekran. Szerokość 320, gdy telefon jest obrócony w trybie poziomym, i wykrywa ekran. Szerokość 569, gdy telefon jest obrócony w trybie pionowym! Dlaczego??
IgorGanapolsky
1
Wyjaśnij: Ci, którzy szukają rozwiązania, które działa również na iOS, powinni spojrzeć na dwóch-głupców lub moją odpowiedź.
mklement0
3
Nie ma potrzeby używania hacka dwóch bitów dla iOS. Wystarczy użyć screen.width i screen.height na Androidzie i na iOS użyj window.innerWidth i window.innerHeight.
Justin
224

Rzeczywiste zachowanie na różnych urządzeniach jest niespójne . Zdarzenia zmiany rozmiaru i orientacji mogą być uruchamiane w innej sekwencji z różną częstotliwością. Ponadto niektóre wartości (np. Screen.width i window.orientation) nie zawsze zmieniają się zgodnie z oczekiwaniami. Unikaj screen.width - nie zmienia się podczas obracania w iOS.

Wiarygodne podejście polega na nasłuchiwaniu zarówno zdarzeń zmiany rozmiaru, jak i orientacji Zmień (z pewnymi ankietami jako zaczepem bezpieczeństwa), a ostatecznie uzyskasz prawidłową wartość orientacji. Podczas moich testów urządzenia z Androidem czasami nie uruchamiają zdarzeń podczas obracania o pełne 180 stopni, więc dołączyłem również setInterval do odpytywania orientacji.

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

Oto wyniki z czterech urządzeń, które przetestowałem (przepraszam za tabelę ASCII, ale wydawało się, że to najłatwiejszy sposób na przedstawienie wyników). Oprócz spójności między urządzeniami z iOS istnieje wiele różnych urządzeń. UWAGA: Zdarzenia są wymienione w kolejności ich uruchomienia.

| ================================================= ============================= |
| Urządzenie | Wystrzelone zdarzenia | orientacja | innerWidth | screen.width |
| ================================================= ============================= |
| iPad 2 | zmiana rozmiaru | 0 | 1024 | 768 |
| (do krajobrazu) zmiana orientacji | 90 | 1024 | 768 |
| ---------------- + ------------------- + ------------ - + ------------ + -------------- |
| iPad 2 | zmiana rozmiaru | 90 | 768 | 768 |
| (do portretu) | zmiana orientacji | 0 | 768 | 768 |
| ---------------- + ------------------- + ------------ - + ------------ + -------------- |
| iPhone 4 | zmiana rozmiaru | 0 | 480 | 320 |
| (do krajobrazu) zmiana orientacji | 90 | 480 | 320 |
| ---------------- + ------------------- + ------------ - + ------------ + -------------- |
| iPhone 4 | zmiana rozmiaru | 90 | 320 | 320 |
| (do portretu) | zmiana orientacji | 0 | 320 | 320 |
| ---------------- + ------------------- + ------------ - + ------------ + -------------- |
| Telefon Droid | zmiana orientacji | 90 | 320 | 320 |
| (do krajobrazu) zmiana rozmiaru | 90 | 569 | 569 |
| ---------------- + ------------------- + ------------ - + ------------ + -------------- |
| Telefon Droid | zmiana orientacji | 0 | 569 | 569 |
| (do portretu) | zmiana rozmiaru | 0 | 320 | 320 |
| ---------------- + ------------------- + ------------ - + ------------ + -------------- |
| Samsung Galaxy | zmiana orientacji | 0 | 400 | 400 |
| Tablet | zmiana orientacji | 90 | 400 | 400 |
| (do krajobrazu) zmiana orientacji | 90 | 400 | 400 |
| | zmiana rozmiaru | 90 | 683 | 683 |
| | zmiana orientacji | 90 | 683 | 683 |
| ---------------- + ------------------- + ------------ - + ------------ + -------------- |
| Samsung Galaxy | zmiana orientacji | 90 | 683 | 683 |
| Tablet | zmiana orientacji | 0 | 683 | 683 |
| (do portretu) | zmiana orientacji | 0 | 683 | 683 |
| | zmiana rozmiaru | 0 | 400 | 400 |
| | zmiana orientacji | 0 | 400 | 400 |
| ---------------- + ------------------- + ------------ - + ------------ + -------------- |
dwubitowy głupiec
źródło
W emulatorze iOS5, jeśli odświeżysz w układzie poziomym, a następnie obrócisz, ten kod nie zostanie uruchomiony.
pracował
1
Świetna odpowiedź. previousOrientationnależy zainicjować z obecną orientacją: var previousOrientation = window.orientation;jeśli chcesz zignorować obrót o 180 stopni, tzn. nie musisz rozróżniać między krajobrazem z lewej lub prawej strony a wariantami odwróconymi do góry nogami, dodaj następujące jako pierwsza linia do checkOrientation(): if (0 === (previousOrientation + window.orientation) % 180) return;Jednak bez dodatkowych setTimeoutsztuczek skorzystasz z tego tylko na iOS, gdzie szybki obrót o 180 stopni tworzy tylko jedno orientationchange wydarzenie.
mklement0
Dzięki @mklement, poprawiłem kod, aby zainicjować poprzednią Orientację.
dwubitowy głupiec
Pozdrawiam za świetną informację. To działało mi na myśl, ponieważ Windows Phone 8.1 nie zawiera zdarzenia zmiany rozmiaru ani zmiany orientacji podczas korzystania z Cordova. Zastosowano użycie setInterval oraz jako bezpieczne.
Perfection
@ mklement0 Do dziś okno. orientacja będzie zawsze niezdefiniowana w Windows Phone 8.1.
Perfekcja
39

doskonała odpowiedź two-bit-głupca zapewnia całe tło, ale pozwól mi spróbować zwięzłego, pragmatycznego podsumowania, jak radzić sobie ze zmianami orientacji w iOS i Androidzie :

  • Jeśli zależy Ci tylko na wymiarach okna (typowy scenariusz) - a nie na konkretnej orientacji:
    • Obsługuj resizetylko wydarzenie.
    • W swoim przewodniku działaj tylko window.innerWidthi window.InnerHeightwyłącznie.
    • NIE używaj window.orientation- nie będzie aktualne na iOS.
  • Jeśli zależy Ci na konkretnej orientacji :
    • Obsługiwać tylko na resizeimprezę, na Androida i tylko na orientationchangezdarzenie na iOS.
    • W swoim przewodniku działaj na window.orientation( window.innerWidthi window.InnerHeight)

Podejścia te oferują niewielkie korzyści w porównaniu z zapamiętywaniem poprzedniej orientacji i porównywaniem:

  • podejście oparte tylko na wymiarach działa również podczas opracowywania w przeglądarkach komputerowych, które w innym przypadku mogą symulować urządzenia mobilne, np. Chrome 23. ( window.orientationnie jest dostępny w przeglądarkach komputerowych).
  • nie ma potrzeby stosowania zmiennej globalnej / anonimowej-na poziomie pliku-na poziomie opakowania.
mklement0
źródło
Problem polega na tym, że gdy zdarzenie zmiany rozmiaru lub orientacji zostanie uruchomione, okno.in.inWidth zgłasza błąd, a urządzenia z
Androidem
@albanx, który wciąż stanowi problem w chrome na iOS: / safari jest w porządku, bo
oldboy
12

Zawsze możesz odsłuchać zdarzenie zmiany rozmiaru okna. Jeśli w takim przypadku okno zmieniło się z wyższego niż szerokie na szersze niż wysokie (lub odwrotnie), możesz być całkiem pewien, że orientacja telefonu została właśnie zmieniona.

Joel Mueller
źródło
To dobry pomysł, spróbuję tego (i poproś mojego przyjaciela z telefonem z Androidem o przetestowanie!)
philnash
Właśnie zdałem sobie sprawę, że ta metoda nie zapewnia orientacji telefonu. Będę wiedział, czy jest to portret, czy krajobraz, ale nie, czy jest do góry nogami, czy też został obrócony w lewo lub w prawo. Jakieś dalsze pomysły?
philnash
Nie jestem pewien, jak może to mieć znaczenie ... Dlaczego musisz wiedzieć, czy telefon jest do góry nogami? Przeglądarka telefonu ma górę, a strona internetowa będzie zorientowana na górę przeglądarki. Każdy użytkownik z dwoma komórkami mózgowymi do zacierania się, który patrzy na stronę internetową do góry nogami, po prostu odwróci telefon, jeśli chce zobaczyć ją z prawej strony
Joel Mueller
1
To trochę trudne. Chciałbym wiedzieć, że mogę wyświetlać różne treści w zależności od orientacji ekranu, mogą to być maksymalnie 4 różne strony, co wymaga od przeglądarki sprawdzenia, czy została obrócona o 0, 90, 180 i 270 stopni. To wszystko jest możliwe, w JavaScript, na iPhonie i dlatego pytam.
philnash
Nadal trudno mi sobie wyobrazić, co strona internetowa mogłaby zrobić inaczej, gdy urządzenie, na którym jest renderowana, jest obrócone o 270 stopni, ale jeśli powiesz, że masz prawidłowy przypadek użycia, nie będę się spierać. W takim przypadku: przepraszam, ale nie mam pojęcia, czy przeglądarka systemu Android zapewnia ten poziom szczegółowości.
Joel Mueller
3

Jest to możliwe w HTML5.
Możesz przeczytać więcej (i wypróbować demo na żywo) tutaj: http://slides.html5rocks.com/#slide-orientation .

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

Obsługuje również przeglądarki deskop, ale zawsze zwraca tę samą wartość.

Derek 朕 會 功夫
źródło
4
To wydarzenie jest naprawdę bardziej dla dostępu do czujników ruchu, chociaż przypuszczam, że może być również użyte do wykrycia zmiany orientacji.
René
Na moim Androidzie Galaxy S2 nie jest obsługiwany w standardowej przeglądarce ani w przeglądarce Dolphin Browser. Ale działa dobrze z mobilnym firefoxem.
Eduardo
3

Miałem ten sam problem. Korzystam z telefonów komórkowych Phonegap i Jquery dla urządzeń z systemem Adroid. Aby właściwie zmienić rozmiar, musiałem ustawić limit czasu:

$(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);
}
Tauanz
źródło
2

Oto rozwiązanie:

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");
            }   
        });
    }
Shishir Arora
źródło
Jest to rozwiązanie, które działało dla mnie najlepiej. Wiem, że nie jest w 100% dokładne, ale możesz wykryć poziomo w stosunku do pionu za pomocą tego: var screenWidth = $ (window) .width (); var screenHeight = $ (window) .height (); if (screenWidth> screenHeight) {doSomething (); }
math0ne,
To było dla mnie rozwiązanie na gównianym tablecie z Androidem. Window.onresize, attachevent i addeventlistener nie powiodły się w przypadku wielu zdarzeń (zmiana rozmiaru, zmiana rozmiaru, zmiana orientacji, orientacja urządzenia). Działa tylko Jquery $ (window) .on ().
Lego
1

Kolejna gotcha - niektóre tablety z Androidem (uważam, że Motorola Xoom i niższy Elonex, na którym przeprowadzam testy, prawdopodobnie też i inne) mają skonfigurowane akcelerometry, aby okno.orientacja == 0 w trybie KRAJOBRAZ, a nie portret !

James-Geldart
źródło
1

możesz wypróbować rozwiązanie kompatybilne ze wszystkimi przeglądarkami.

Poniżej znajduje się orientationchangepic kompatybilności: zgodność dlatego, ja orientaionchangepiszę polifill, jest on oparty na atrybucie @media do naprawy biblioteki narzędziowej orientacji --—orientchange -fix

window.addEventListener('orientationchange', function(){
 if(window.neworientation.current === 'portrait|landscape'){
    // do something……
 } else {
    // do something……
 }
}, false);
Zhansingsong
źródło
0

Warto zauważyć, że na moim urządzeniu Epic 4G Touch musiałem skonfigurować widok internetowy, aby korzystać z WebChromeClient, zanim zadzwoni javascript.

webView.setWebChromeClient(new WebChromeClient());
calebisstupid
źródło
0

Sposób na przeglądarkę

$(window).on('resize orientationchange webkitfullscreenchange mozfullscreenchange fullscreenchange',  function(){
//code here
});
comonitos
źródło
-1

Mały wkład w odpowiedź dwumitowego głupca:

Jak opisano w tabeli na telefonach z systemem Android, zdarzenie „orientacja” jest uruchamiane wcześniej niż zdarzenie „zmiana rozmiaru”, blokując w ten sposób następne wywołanie zmiany rozmiaru (z powodu instrukcji if). Właściwość Szerokość nadal nie jest ustawiona.

Obejściem, choć może nie idealnym, może być niewypuszczenie zdarzenia „zmiana orientacji”. Można to zarchiwizować, zawijając powiązanie zdarzenia „orientacja wymiany” w instrukcji „if”:

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

Mam nadzieję, że to pomoże

(testy przeprowadzono na Nexusie S)

Alex
źródło