Wie erkenne ich Orientierungsänderungen mit Phonegap unter iOS korrekt?

178

Ich habe diesen Orientierungstestcode unten gefunden und nach JQTouch-Referenzmaterial gesucht. Dies funktioniert im iOS-Simulator auf Mobile Safari korrekt, wird jedoch in Phonegap nicht korrekt behandelt. Mein Projekt stößt auf dasselbe Problem, das diese Testseite beendet. Gibt es eine Möglichkeit, die Orientierungsänderung mithilfe von JavaScript in Phonegap zu erfassen?

window.onorientationchange = function() {
  /*window.orientation returns a value that indicates whether iPhone is in portrait mode, landscape mode with the screen turned to the
    left, or landscape mode with the screen turned to the right. */
  var orientation = window.orientation;
  switch (orientation) {
    case 0:
      /* If in portrait mode, sets the body's class attribute to portrait. Consequently, all style definitions matching the body[class="portrait"] declaration
         in the iPhoneOrientation.css file will be selected and used to style "Handling iPhone or iPod touch Orientation Events". */
      document.body.setAttribute("class", "portrait");

      /* Add a descriptive message on "Handling iPhone or iPod touch Orientation Events"  */
      document.getElementById("currentOrientation").innerHTML = "Now in portrait orientation (Home button on the bottom).";
      break;

    case 90:
      /* If in landscape mode with the screen turned to the left, sets the body's class attribute to landscapeLeft. In this case, all style definitions matching the
         body[class="landscapeLeft"] declaration in the iPhoneOrientation.css file will be selected and used to style "Handling iPhone or iPod touch Orientation Events". */
      document.body.setAttribute("class", "landscape");

      document.getElementById("currentOrientation").innerHTML = "Now in landscape orientation and turned to the left (Home button to the right).";
      break;

    case -90:
      /* If in landscape mode with the screen turned to the right, sets the body's class attribute to landscapeRight. Here, all style definitions matching the
         body[class="landscapeRight"] declaration in the iPhoneOrientation.css file will be selected and used to style "Handling iPhone or iPod touch Orientation Events". */
      document.body.setAttribute("class", "landscape");

      document.getElementById("currentOrientation").innerHTML = "Now in landscape orientation and turned to the right (Home button to the left).";
      break;
  }
}
Ajpalma
quelle
Mögliches Duplikat von Orientierungsänderung mit Javascript erkennen
Gajus

Antworten:

296

Das ist was ich mache:

function doOnOrientationChange() {
    switch(window.orientation) {  
      case -90: case 90:
        alert('landscape');
        break; 
      default:
        alert('portrait');
        break; 
    }
}
  
window.addEventListener('orientationchange', doOnOrientationChange);
  
// Initial execution if needed
doOnOrientationChange();


Update Mai 2019: window.orientation ist eine veraltete Funktion und wird von den meisten Browsern laut MDN nicht unterstützt . Das orientationchangeEreignis ist mit window.orientation verbunden und sollte daher wahrscheinlich nicht verwendet werden.

Benny Neugebauer
quelle
3
Das ist die einzige Lösung, die für mich aus dieser Diskussion heraus funktioniert :) +1
Atadj
9
Ich habewindow.onorientationchange = function() { setTimeout(functionName, 0); };
Kirk Strobeck
11
Warum haben Sie aus Interesse setTimeout Kirk verwendet?
Backdesk
10
Achtung! Dies ist gerätespezifisch - die Grade beziehen sich auf den Unterschied zur Standardausrichtung des Geräts. Mit anderen Worten, wenn das Tablet für die Verwendung im Querformat ausgelegt ist, bedeutet 90, dass es sich im Hochformat befindet. Um dies zu umgehen, überprüfe ich zunächst die Höhe und Breite des Fensters, um die Ausrichtung zu speichern, und verwende Orientierungsänderung, um dies zu aktualisieren, wenn sich etwas ändert.
Benallansmith
15
Außerdem habe ich festgestellt, dass die Orientierungsänderung ausgelöst wird, bevor die Breite und Höhe geändert werden. Daher ist eine gewisse Verzögerung erforderlich, um die Ausrichtung anhand der Breite und Höhe korrekt zu erkennen. Dazu speichere ich die aktuelle Ausrichtung und wenn eine Änderung festgestellt wird, überprüfe ich die Änderung der Ausrichtung in Schritten von 50 ms bis zu 250 ms. Sobald ein Unterschied festgestellt wurde, aktualisiere ich die Seite entsprechend. Auf meinem Nexus 5 erkennt es normalerweise den Unterschied zwischen Breite und Höhe nach 150 ms.
Benallansmith
24

Ich verwende window.onresize = function(){ checkOrientation(); } Und in checkOrientation können Sie window.orientation oder body width check verwenden, aber die Idee ist, dass "window.onresize" die browserübergreifendste Methode ist, zumindest bei den meisten mobilen und Desktop-Browsern, die ich hatte Gelegenheit zum Testen mit.

hndcrftd
quelle
1
Das ist ein großartiger Punkt. Wenn Sie mit einer Web-Technologie entwickeln, können Sie mit dieser Methode einfacher in einem Browser debuggen und testen, anstatt sie jedes Mal bereitzustellen / zu simulieren.
Matt Ray
2
Dies ist überhaupt nicht in Ordnung ... denn wenn die Tastatur angezeigt wird, ändert sich die Größe (und dies ist nicht der einzige Fall). Also ein großes Nein dafür!
HellBaby
2
@HellBaby Wenn die Tastatur angezeigt wird, wird die Funktion aufgerufen. Je nachdem, welche Methode Sie zur Orientierungserkennung verwenden, wird jedoch festgestellt, dass sich die Ausrichtung NICHT GEÄNDERT hat, wie dies bei window.orientation der Fall wäre. Also stehe ich immer noch zu meiner Antwort.
hndcrftd
1
@Raine Ich habe diese Methode auf einem Ipad 4 verwendet und musste sie aufgrund dieses Problems ändern. Vielleicht funktioniert es für einige Geräte, aber nicht für alle.
HellBaby
1
@MattRay Mit den neuesten Entwicklungs-Toolkits, die diese Art von Geräteverhalten emulieren können, können Sie Orientierungsänderungen problemlos testen.
Kontur
14
if (window.matchMedia("(orientation: portrait)").matches) {
   // you're in PORTRAIT mode
}

if (window.matchMedia("(orientation: landscape)").matches) {
  // you're in LANDSCAPE mode
}
Alyssa Reyes
quelle
1
Sie können es an ein resizeEreignis anhängen . IIRC, diese Abfragen funktionieren jedoch nicht richtig, wenn die Tastatur geöffnet ist.
adi518
12

Ich bin auch ziemlich neu in iOS und Phonegap, aber ich konnte dies tun, indem ich einen eventListener hinzufügte. Ich habe das Gleiche getan (anhand des Beispiels, auf das Sie verweisen) und konnte es nicht zum Laufen bringen. Aber das schien den Trick zu tun:

// Event listener to determine change (horizontal/portrait)
window.addEventListener("orientationchange", updateOrientation); 

function updateOrientation(e) {
switch (e.orientation)
{   
    case 0:
        // Do your thing
        break;

    case -90:
        // Do your thing
        break;

    case 90:
        // Do your thing
        break;

    default:
        break;
    }
}

Möglicherweise haben Sie Glück, wenn Sie in der PhoneGap-Google-Gruppe nach dem Begriff "Orientierung" suchen .

Ein Beispiel, über das ich als Beispiel gelesen habe, wie man Orientierung erkennt, war Pie Guy: ( Spiel , JS-Datei ). Es ähnelt dem Code, den Sie gepostet haben, aber wie Sie ... Ich konnte ihn nicht zum Laufen bringen.

Eine Einschränkung: Der eventListener hat für mich gearbeitet, aber ich bin mir nicht sicher, ob dies ein zu intensiver Ansatz ist. Bisher war es der einzige Weg, der für mich funktioniert hat, aber ich weiß nicht, ob es bessere, schlankere Wege gibt.


UPDATE hat den obigen Code behoben, es funktioniert jetzt

Vermeidung
quelle
Dan
5

Während der Arbeit mit dem orientationchangeEreignis benötigte ich eine Zeitüberschreitung, um die richtigen Abmessungen der Elemente auf der Seite zu erhalten, aber matchMedia funktionierte einwandfrei. Mein letzter Code:

var matchMedia = window.msMatchMedia || window.MozMatchMedia || window.WebkitMatchMedia || window.matchMedia;

if (typeof(matchMedia) !== 'undefined') {
  // use matchMedia function to detect orientationchange
  window.matchMedia('(orientation: portrait)').addListener(function() {
    // your code ...
  });
} else {
  // use orientationchange event with timeout (fires to early)
  $(window).on('orientationchange', function() {
    window.setTimeout(function() {
      // your code ...
    }, 300)
  });
}
Oncode
quelle
3

Ich glaube, dass die richtige Antwort bereits veröffentlicht und akzeptiert wurde, aber es gibt ein Problem, das ich selbst erlebt habe und das einige andere hier erwähnt haben.

Auf bestimmten Plattformen werden verschiedene Eigenschaften wie Fensterabmessungen ( window.innerWidth, window.innerHeight) und die window.orientationEigenschaft zum Zeitpunkt des Auslösens des Ereignisses nicht aktualisiert "orientationchange". Viele Male, die Eigenschaft window.orientationist undefinedfür wenige Millisekunden nach dem Brennen von"orientationchange" (zumindest ist es in Chrome auf iOS).

Der beste Weg, um mit diesem Problem umzugehen, war:

var handleOrientationChange = (function() {
    var struct = function(){
        struct.parse();
    };
    struct.showPortraitView = function(){
        alert("Portrait Orientation: " + window.orientation);
    };
    struct.showLandscapeView = function(){
        alert("Landscape Orientation: " + window.orientation);
    };
    struct.parse = function(){
        switch(window.orientation){
            case 0:
                    //Portrait Orientation
                    this.showPortraitView();
                break;
            default:
                    //Landscape Orientation
                    if(!parseInt(window.orientation) 
                    || window.orientation === this.lastOrientation)
                        setTimeout(this, 10);
                    else
                    {
                        this.lastOrientation = window.orientation;
                        this.showLandscapeView();
                    }
                break;
        }
    };
    struct.lastOrientation = window.orientation;
    return struct;
})();
window.addEventListener("orientationchange", handleOrientationChange, false);

Ich überprüfe, ob die Ausrichtung entweder undefiniert ist oder ob die Ausrichtung der zuletzt erkannten Ausrichtung entspricht. Wenn beides zutrifft, warte ich zehn Millisekunden und analysiere dann die Ausrichtung erneut. Wenn die Ausrichtung ein richtiger Wert ist, rufe ich dieshowXOrientation Funktionen auf. Wenn die Ausrichtung ungültig ist, schleife ich meine Überprüfungsfunktion weiter und warte jedes Mal zehn Millisekunden, bis sie gültig ist.

Jetzt würde ich eine JSFiddle dafür erstellen, wie ich es normalerweise getan habe, aber JSFiddle hat nicht für mich gearbeitet und mein Support-Fehler dafür wurde geschlossen, da niemand anderes das gleiche Problem meldet. Wenn jemand anderes daraus eine JSFiddle machen möchte, fahren Sie bitte fort.

Vielen Dank! Ich hoffe das hilft!

WebWanderer
quelle
Zu Ihrer Information, bei ersten Tests sah ich ein Problem: Ich drehe ein paar Mal im Uhrzeigersinn und eine Warnung sagte "Landschaftsorientierung: 180", obwohl mein Gerät physisch als Porträt ausgerichtet war.
MarsAndBack
2

Folgendes habe ich getan:

window.addEventListener('orientationchange', doOnOrientationChange);

function doOnOrientationChange()
{
      if (screen.height > screen.width) {
         console.log('portrait');
      } else {
         console.log('landscape');
      }
}
Raul Gomez
quelle
2

Obwohl sich die Frage nur auf die Nutzung von PhoneGap und iOS bezieht und bereits beantwortet wurde, kann ich der umfassenderen Frage der Erkennung der Bildschirmorientierung mit JS im Jahr 2019 einige Punkte hinzufügen:

  1. window.orientationDie Eigenschaft ist veraltet und wird von Android-Browsern nicht unterstützt. Es gibt eine neuere Eigenschaft, die weitere Informationen zur Ausrichtung bietet screen.orientation. Es ist jedoch noch experimentell und wird von iOS Safari nicht unterstützt . Um das beste Ergebnis zu erzielen, müssen Sie wahrscheinlich die Kombination der beiden verwenden : const angle = screen.orientation ? screen.orientation.angle : window.orientation.

  2. Wie @benallansmith in seinem Kommentar erwähnt hat , wird das window.onorientationchangeEreignis zuvor ausgelöst window.onresize, sodass Sie die tatsächlichen Abmessungen des Bildschirms nur erhalten, wenn Sie nach dem Ereignis "Orientierungsänderung" eine Verzögerung hinzufügen.

  3. Es gibt ein Cordova Screen Orientation Plugin zur Unterstützung älterer mobiler Browser, aber ich glaube, dass es heutzutage nicht mehr nötig ist, es zu verwenden.

  4. Es gab auch ein screen.onorientationchangeEreignis, aber es ist veraltet und sollte nicht verwendet werden. Nur zur Vollständigkeit der Antwort hinzugefügt.

In meinem Anwendungsfall war mir die tatsächliche Ausrichtung nicht wichtig, sondern die tatsächliche Breite und Höhe des Fensters, die sich offensichtlich mit der Ausrichtung ändert. Daher habe ich resizeevent verwendet, um Verzögerungen zwischen dem orientationchangeEreignis und der Aktualisierung der Fensterdimensionen zu vermeiden :

window.addEventListener('resize', () => {
  console.log(`Actual dimensions: ${window.innerWidth}x${window.innerHeight}`);
  console.log(`Actual orientation: ${screen.orientation ? screen.orientation.angle : window.orientation}`);
});

Hinweis 1: Ich habe hier die EcmaScript 6-Syntax verwendet. Stellen Sie sicher, dass Sie sie bei Bedarf in ES5 kompilieren.

Hinweis 2: Das window.onresizeEreignis wird auch ausgelöst, wenn die virtuelle Tastatur umgeschaltet wird , nicht nur, wenn sich die Ausrichtung ändert.

Alexey Grinko
quelle
1

Ich habe diesen Code gefunden, um zu erkennen, ob sich das Gerät im Querformat befindet, und in diesem Fall eine Begrüßungsseite mit der Aufschrift "Ausrichtung ändern, um die Site anzuzeigen" hinzuzufügen. Es funktioniert auf iOS, Android und Windows Phones. Ich denke, dass dies sehr nützlich ist, da es ziemlich elegant ist und es vermieden wird, eine Landschaftsansicht für die mobile Site festzulegen. Der Code funktioniert sehr gut. Das einzige, was nicht ganz zufriedenstellend ist, ist, dass die Begrüßungsseite nicht angezeigt wird, wenn jemand die Seite in der Querformatansicht lädt.

<script>
(function() {
    'use strict';

    var isMobile = {
        Android: function() {
            return navigator.userAgent.match(/Android/i);
        },
        BlackBerry: function() {
            return navigator.userAgent.match(/BlackBerry/i);
        },
        iOS: function() {
            return navigator.userAgent.match(/iPhone|iPad|iPod/i);
        },
        Opera: function() {
            return navigator.userAgent.match(/Opera Mini/i);
        },
        Windows: function() {
            return navigator.userAgent.match(/IEMobile/i);
        },
        any: function() {
            return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Opera() || isMobile.Windows());
        }
    };
    if (isMobile.any()) {
        doOnOrientationChange();
        window.addEventListener('resize', doOnOrientationChange, 'false');
    }

    function doOnOrientationChange() {
        var a = document.getElementById('alert');
        var b = document.body;
        var w = b.offsetWidth;
        var h = b.offsetHeight;
        (w / h > 1) ? (a.className = 'show', b.className = 'full-body') : (a.className = 'hide', b.className = '');
    }
})();
</script>

Und der HTML: <div id="alert" class="hide"> <div id="content">This site is not thought to be viewed in landscape mode, please turn your device </div> </div>

Luigi
quelle
1
if (window.DeviceOrientationEvent) {
    // Listen for orientation changes
    window.addEventListener("orientationchange", orientationChangeHandler);
    function orientationChangeHandler(evt) {
        // Announce the new orientation number
        // alert(screen.orientation);
        // Find matches
        var mql = window.matchMedia("(orientation: portrait)");

        if (mql.matches)  //true
    }
}
M Fauzi Riozi
quelle
-1

Folgendes hat bei mir funktioniert:

function changeOrientation(){
switch(window.orientation) {
case 0: // portrait, home bottom
case 180: // portrait, home top
 alert("portrait H: "+$(window).height()+" W: "+$(window).width());       
 break;
          case -90: // landscape, home left
          case 90: // landscape, home right
        alert("landscape H: "+$(window).height()+" W: "+$(window).width());
            break;
        }
    }

 window.onorientationchange = function() { 
            //Need at least 800 milliseconds
            setTimeout(changeOrientation, 1000);
        }

Ich brauchte das Timeout, da der Wert von window.orientationnicht sofort aktualisiert wird

Katalysator294
quelle
-2

Ich erstelle eine jQTouch-App in PhoneGap für das iPhone. Ich habe seit Tagen mit diesem Problem gekämpft. Ich habe die Eventlistener-Lösung einige Male vorgeschlagen, konnte sie aber einfach nicht zum Laufen bringen.

Am Ende habe ich eine andere Lösung gefunden. Grundsätzlich wird die Breite des Körpers regelmäßig mit Settimeout überprüft. Wenn die Breite 320 beträgt, ist die Ausrichtung Hochformat, wenn 480 Querformat. Wenn sich die Ausrichtung seit der letzten Überprüfung geändert hat, wird entweder eine Hochformat- oder eine Querformatfunktion ausgelöst, in der Sie Ihr Ding für jede Ausrichtung ausführen können.

Code (Hinweis, ich weiß, dass der Code einige Wiederholungen enthält, habe mich aber noch nicht darum gekümmert, ihn zu kürzen!):

// get original orientation based on body width
deviceWidth = $('body').width();
if (deviceWidth == 320) {
    currentOrientation = "portrait";
}
else if (deviceWidth == 480) {
    currentOrientation = "landscape";
}

// fire a function that checks the orientation every x milliseconds
setInterval(checkOrientation, 500);

// check orientation
function checkOrientation() {
    deviceWidth = $('body').width();
    if (deviceWidth == '320') {
        newOrientation = "portrait";
    }
    else if (deviceWidth == '480') {
        newOrientation = "landscape";
    }
    // if orientation changed since last check, fire either the portrait or landscape function
    if (newOrientation != currentOrientation) {
        if (newOrientation == "portrait") {
            changedToPortrait();
        }
        else if (newOrientation == "landscape") {
            changedToLandscape();
        }
        currentOrientation = newOrientation;
    }
}

// landscape stuff
function changedToLandscape() {
    alert('Orientation has changed to Landscape!');
}

// portrait stuff
function changedToPortrait() {
    alert('Orientation has changed to Portrait!');
}
Danny Connell
quelle
8
Die Hardcodierung des Geräts auf 320 oder 480 funktioniert in Zukunft oder mit aktuellen hochauflösenden Telefonen nicht mehr.
Fresheyeball
1
1) Sie sollten ein onresizeEreignis verwenden, das sofort ausgelöst wird, nicht innerhalb von 500 Millisekunden. 2) Dieser Code ist androidspezifisch. Verwenden Sie ihn onorientationchangestattdessen für das iPhone. 3) Testen Sie, ob er im Browser unterstützt wird:"onorientationchange" in window
Dan