Rileva la rotazione del telefono Android nel browser con JavaScript


188

So che in Safari su iPhone è possibile rilevare l'orientamento dello schermo e il cambiamento di orientamento ascoltando l' onorientationchangeevento e interrogando window.orientationl'angolazione.

È possibile nel browser su telefoni Android?

Per essere chiari, chiedo se la rotazione di un dispositivo Android può essere rilevata da JavaScript in esecuzione su una pagina Web standard. È possibile su un iPhone e mi chiedevo se potesse essere fatto per i telefoni Android.

Risposte:


214

Per rilevare una modifica dell'orientamento su un browser Android, collegare un ascoltatore all'evento orientationchangeo resizesu 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);

Controlla la window.orientationproprietà per capire in che modo è orientato il dispositivo. Con telefoni Android screen.widtho screen.heightanche aggiornamenti quando il dispositivo viene ruotato. (questo non è il caso dell'iPhone).


funziona davvero? ho provato jquery $ (window) .bind ("orientchange", fn); ma non ha funzionato, devo usare il modulo sopra? ho provato "onorientationchange" nella finestra, ripete false
Ayyash

Funziona bene. Ayyash - il punto qui è che quando "l'orientamento al cambio" non è supportato, ricadrà su "ridimensionamento"
Dror

9
Sul droide questo è completamente folle. Avvisa screen.width di 320 quando il telefono viene ruotato in modalità orizzontale e rileva screen.width 569 quando il telefono viene ruotato in modalità verticale! Come mai??
IgorGanapolsky,

1
Solo per chiarire: chi è alla ricerca di una soluzione che funzioni anche su iOS dovrebbe guardare a due bit-idioti o alla mia risposta.
mklement0

3
Non c'è bisogno di usare l'hack di due bit-stupidi per iOS. Usa semplicemente screen.width e screen.height su Android e su iOS usa window.innerWidth e window.innerHeight.
Justin

225

Il comportamento effettivo su diversi dispositivi è incoerente . Gli eventi di ridimensionamento e orientamento possono cambiare in una sequenza diversa con frequenza variabile. Inoltre, alcuni valori (ad es. Screen.width e window.orientation) non cambiano sempre quando ci si aspetta. Evita screen.width : non cambia quando si ruota in iOS.

L'approccio affidabile è quello di ascoltare sia gli eventi di ridimensionamento che quelli di orientamento (con alcuni polling come dispositivo di sicurezza) e alla fine otterrai un valore valido per l'orientamento. Nei miei test, i dispositivi Android occasionalmente non attivano eventi quando ruotano di 180 gradi, quindi ho anche incluso un setInterval per eseguire il polling dell'orientamento.

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

Ecco i risultati dei quattro dispositivi che ho testato (scusate la tabella ASCII, ma mi è sembrato il modo più semplice per presentare i risultati). A parte la coerenza tra i dispositivi iOS, c'è molta varietà tra i dispositivi. NOTA: gli eventi sono elencati nell'ordine in cui sono stati attivati.

| ================================================= ============================= |
| Dispositivo | Eventi licenziati | orientamento | innerWidth | screen.width |
| ================================================= ============================= |
| iPad 2 | ridimensionare | 0 | 1024 | 768 |
| (al paesaggio) | cambio di orientamento | 90 | 1024 | 768 |
| ---------------- + ------------------- + ------------ - + ------------ + -------------- |
| iPad 2 | ridimensionare | 90 | 768 | 768 |
| (al ritratto) | cambio di orientamento | 0 | 768 | 768 |
| ---------------- + ------------------- + ------------ - + ------------ + -------------- |
| iPhone 4 | ridimensionare | 0 | 480 | 320 |
| (al paesaggio) | cambio di orientamento | 90 | 480 | 320 |
| ---------------- + ------------------- + ------------ - + ------------ + -------------- |
| iPhone 4 | ridimensionare | 90 | 320 | 320 |
| (al ritratto) | cambio di orientamento | 0 | 320 | 320 |
| ---------------- + ------------------- + ------------ - + ------------ + -------------- |
| Telefono Droid | cambio di orientamento | 90 | 320 | 320 |
| (al paesaggio) | ridimensionare | 90 | 569 | 569 |
| ---------------- + ------------------- + ------------ - + ------------ + -------------- |
| Telefono Droid | cambio di orientamento | 0 | 569 | 569 |
| (al ritratto) | ridimensionare | 0 | 320 | 320 |
| ---------------- + ------------------- + ------------ - + ------------ + -------------- |
| Samsung Galaxy | cambio di orientamento | 0 | 400 | 400 |
| Tablet | cambio di orientamento | 90 | 400 | 400 |
| (al paesaggio) | cambio di orientamento | 90 | 400 | 400 |
| | ridimensionare | 90 | 683 | 683 |
| | cambio di orientamento | 90 | 683 | 683 |
| ---------------- + ------------------- + ------------ - + ------------ + -------------- |
| Samsung Galaxy | cambio di orientamento | 90 | 683 | 683 |
| Tablet | cambio di orientamento | 0 | 683 | 683 |
| (al ritratto) | cambio di orientamento | 0 | 683 | 683 |
| | ridimensionare | 0 | 400 | 400 |
| | cambio di orientamento | 0 | 400 | 400 |
| ---------------- + ------------------- + ------------ - + ------------ + -------------- |

Nell'emulatore iOS5, se si aggiorna in orizzontale quindi si ruota, questo codice non si attiva.
funzionato

1
Bella risposta. previousOrientationdeve essere inizializzato con l'orientamento allora corrente: var previousOrientation = window.orientation;se si desidera ignorare le rotazioni di 180 gradi, ovvero non è necessario distinguere tra il panorama a sinistra o a destra e le varianti capovolte o no, aggiungere quanto segue come prima riga di checkOrientation(): if (0 === (previousOrientation + window.orientation) % 180) return;Tuttavia, senza ulteriori setTimeoutaccorgimenti, ne trarrai vantaggio solo su iOS, dove una rapida rotazione di 180 gradi crea solo un singolo orientationchange evento.
mklement0

Grazie @mklement, ho modificato il codice per inizializzare l'Orientation precedente.
due scemi l'

Saluti per l'ottima informazione. Questo mi stava facendo impazzire perché Windows Phone 8.1 non presenta un evento di ridimensionamento o cambio orientamento quando usi Cordova. Ricorso all'uso di setInterval come fail-safe.
Perfezione

@ mklement0 Ad oggi window.orientation sarà sempre indefinito su Windows Phone 8.1.
Perfezione

39

L'eccellente risposta di two-bit-sciocco fornisce tutto lo sfondo, ma lasciami tentare un sommario conciso e pragmatico su come gestire i cambiamenti di orientamento su iOS e Android :

  • Se ti preoccupi solo delle dimensioni della finestra (lo scenario tipico) e non dell'orientamento specifico:
    • Gestisci resizesolo l' evento.
    • Nel tuo gestore, agire window.innerWidthe window.InnerHeightsolo.
    • NON utilizzare window.orientation: non sarà aggiornato su iOS.
  • Se ti interessa l' orientamento specifico :
    • Gestisci solo l' resizeevento su Android e solo l' orientationchangeevento su iOS.
    • Nel tuo gestore, agire su window.orientation(e window.innerWidthe window.InnerHeight)

Questi approcci offrono lievi benefici rispetto al ricordare l'orientamento precedente e al confronto:

  • l'approccio delle sole dimensioni funziona anche durante lo sviluppo su browser desktop che possono altrimenti simulare dispositivi mobili, ad esempio Chrome 23. ( window.orientationnon disponibile su browser desktop).
  • non è necessaria una variabile globale / anonima-livello-file-livello-funzione-wrapper.

Il problema è che quando l'evento ridimensionamento o orientamento attiva la finestra.innerWidth segnala dispositivi Droid e errati
albanx

@albanx che è ancora un problema in Chrome su iOS: / Safari va bene però
oldboy

12

Puoi sempre ascoltare l'evento di ridimensionamento della finestra. Se, in quell'evento, la finestra diventasse più alta di quanto sia larga o più larga di quanto sia alta (o viceversa), puoi essere abbastanza sicuro che l'orientamento del telefono sia stato appena cambiato.


È una buona idea, ci proverò (e chiederò al mio amico con il telefono Android di testare!)
philnash,

Mi sono appena reso conto che questo metodo non mi dà l'orientamento del telefono. Saprò se si tratta di un ritratto o di un paesaggio, ma non se è capovolto o è stato girato a sinistra o a destra. Altre idee?
philnash,

Non sono sicuro di come possa avere importanza ... Perché devi sapere se il telefono è capovolto? Il browser del telefono ha una parte superiore e la pagina Web sarà orientata verso la parte superiore del browser. Qualsiasi utente con due cellule cerebrali da sfogliare che sta guardando una pagina web capovolta girerà semplicemente il telefono se vuole vederlo capovolto
Joel Mueller,

1
È un po 'duro. Sono interessato a sapere in modo da poter mostrare contenuti diversi in base all'orientamento dello schermo, questo potrebbe essere fino a 4 pagine diverse, richiedendo al browser di sapere se era stato ruotato di 0, 90, 180 e 270 gradi. Tutto ciò è possibile, in JavaScript, su iPhone ed è il motivo per cui lo sto chiedendo.
philnash,

Sto ancora facendo fatica a immaginare cosa una pagina Web potrebbe fare utilmente in modo diverso quando il dispositivo su cui viene eseguito il rendering viene ruotato di 270 gradi, ma se dici che hai un caso d'uso valido, non farò cavilli. In tal caso: mi dispiace, ma non ho idea se il browser Android fornisca questo livello di dettaglio.
Joel Mueller,

3

È possibile in HTML5.
Puoi leggere di più (e provare una demo live) qui: http://slides.html5rocks.com/#slide-orientation .

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

Supporta anche i browser da tavolo ma restituirà sempre lo stesso valore.


4
Questo evento è davvero di più per l'accesso ai sensori di movimento, anche se suppongo che possa essere utilizzato anche per rilevare il cambiamento di orientamento.
René,

Sul mio Android Galaxy S2 non è supportato sul browser stock né sul browser Dolphin. Ma funziona bene con Firefox mobile.
Eduardo,

3

Ho avuto lo stesso problema. Sto usando Phonegap e Jquery mobile, per i dispositivi Adroid. Per ridimensionare correttamente ho dovuto impostare un timeout:

$(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

Ecco la soluzione:

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

Questa è la soluzione che ha funzionato meglio per me, so che non è accurata al 100% ma puoi rilevare orizzontale vs verticale usando questo: var screenWidth = $ (window) .width (); var screenHeight = $ (window) .height (); if (screenWidth> screenHeight) {doSomething (); }
math0ne,

Questa è stata la soluzione per me su un tablet Android schifoso. window.onresize, attachevent e addeventlistener non sono riusciti su più eventi (ridimensionamento, ridimensionamento, orientamento, cambio dispositivo). Solo Jquery $ (window) .on () ha funzionato.
Lego

1

Un altro gotcha - alcuni tablet Android (il Motorola Xoom credo e uno Elonex di fascia bassa su cui sto facendo alcuni test, probabilmente anche altri) hanno i loro accelerometri impostati in modo che window.orientation == 0 in modalità LANDSCAPE, non verticale !


1

puoi provare la soluzione, compatibile con tutti i browser.

Di seguito è riportato un esempio di orientationchangecompatibilità: Compatibilità pertanto, orientaionchangecreo un polyfill, è basato sull'attributo @media per correggere la libreria di utilità di orientamento - cambio - orientamento - scambio

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

0

Vale la pena notare che sul mio Epic 4G Touch ho dovuto impostare la visualizzazione Web per utilizzare WebChromeClient prima che funzionasse qualsiasi chiamata Android javascript.

webView.setWebChromeClient(new WebChromeClient());

0

Cross browser way

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

-1

Un piccolo contributo alla risposta del matto:

Come descritto nella tabella sui telefoni droide, l'evento "orientamentocambia" viene generato prima dell'evento "ridimensiona", bloccando così la chiamata di ridimensionamento successiva (a causa dell'istruzione if). La proprietà larghezza non è ancora impostata.

Una soluzione alternativa, sebbene forse non perfetta, potrebbe essere quella di non attivare l'evento "orientamento-cambio". Che può essere archiviato racchiudendo il legame di evento "orientationchange" nell'istruzione "if":

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

Spero che sia d'aiuto

(i test sono stati eseguiti su Nexus S)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.