Bagaimana cara mendeteksi perubahan orientasi dengan benar menggunakan Phonegap di iOS?


178

Saya menemukan kode tes orientasi ini di bawah mencari bahan referensi JQTouch. Ini berfungsi dengan benar di simulator iOS di Safari seluler tetapi tidak ditangani dengan benar di Phonegap. Proyek saya mengalami masalah yang sama dengan membunuh halaman pengujian ini. Apakah ada cara untuk merasakan perubahan orientasi menggunakan JavaScript di Phonegap?

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

Jawaban:


297

Inilah yang saya lakukan:

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


Pembaruan Mei 2019: window.orientation adalah fitur usang dan tidak didukung oleh sebagian besar peramban menurut MDN . The orientationchangeevent terkait dengan window.orientation dan karena itu sebaiknya tidak digunakan.


3
Itulah satu-satunya solusi yang bekerja untuk saya dari diskusi ini :) +1
Atadj

9
Saya lakukanwindow.onorientationchange = function() { setTimeout(functionName, 0); };
Kirk Strobeck

11
Karena ketertarikan, mengapa Anda menggunakan setTimeout Kirk?
backdesk

10
Hati-hati! Ini adalah perangkat khusus - derajat mengacu pada perbedaan dari orientasi standar perangkat. Dengan kata lain, jika tablet dirancang untuk digunakan dalam lanskap, maka 90 berarti tablet itu dalam mode potret. Saat mengerjakan ini, saya awalnya memeriksa tinggi vs lebar jendela untuk menyimpan orientasi, dan menggunakan orientasi untuk memperbarui ini jika ada perubahan.
benallansmith

15
Selain itu, saya telah menemukan bahwa orientasi orientasi menyala sebelum lebar dan tinggi diubah, oleh karena itu diperlukan sedikit penundaan untuk mendeteksi orientasi dengan benar menggunakan lebar dan tinggi. Untuk ini, saya menyimpan orientasi saat ini, dan ketika perubahan terdeteksi, saya memeriksa perubahan orientasi dalam peningkatan 50 ms hingga 250 ms. Setelah perbedaan ditemukan, saya kemudian memperbarui halaman yang sesuai. Pada Nexus 5 saya, biasanya mendeteksi perbedaan lebar vs tinggi setelah 150ms.
benallansmith

24

Saya menggunakan window.onresize = function(){ checkOrientation(); } Dan di checkOrientation Anda dapat menggunakan window.orientation atau pengecekan lebar badan tetapi idenya adalah, "window.onresize" adalah metode peramban yang paling banyak, paling tidak dengan mayoritas peramban seluler dan desktop yang saya miliki. kesempatan untuk menguji dengan.


1
Ini poin yang bagus. Jika Anda mengembangkan menggunakan teknologi yang menghadap web, metode ini memungkinkan Anda untuk debug dan menguji lebih mudah di browser daripada menggunakan / mensimulasikan setiap kali.
Matt Ray

2
Ini tidak baik sama sekali ... karena ketika keyboard muncul itu akan mengubah ukuran (dan ini bukan satu-satunya kasus). Jadi tidak ada yang besar untuk ini!
HellBaby

2
@ HellBaby Ketika keyboard muncul fungsi akan dipanggil, namun, tergantung pada metode apa yang Anda gunakan untuk deteksi orientasi, itu akan mendeteksi bahwa orientasi BELUM BERUBAH, seperti halnya dengan window.orientation. Jadi saya tetap mendukung jawaban saya.
hndcrftd

1
@Raine Saya menggunakan metode itu pada Ipad 4 dan terpaksa mengubahnya karena masalah itu. Jadi mungkin itu berfungsi untuk beberapa perangkat tetapi tidak untuk semua ..
HellBaby

1
@MattRay Anda dapat dengan mudah menguji perubahan orientasi dengan toolkit dev terbaru yang mampu meniru perilaku perangkat semacam ini.
kontur

14
if (window.matchMedia("(orientation: portrait)").matches) {
   // you're in PORTRAIT mode
}

if (window.matchMedia("(orientation: landscape)").matches) {
  // you're in LANDSCAPE mode
}

1
Anda bisa melampirkannya ke suatu resizeacara. Namun, IIRC, kueri ini tidak akan berfungsi dengan benar dengan keyboard.
adi518

12

Saya cukup baru untuk iOS dan Phonegap juga, tapi saya bisa melakukan ini dengan menambahkan eventener. Saya melakukan hal yang sama (menggunakan contoh referensi Anda), dan tidak bisa berfungsi. Tapi ini sepertinya berhasil:

// 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;
    }
}

Anda mungkin beruntung mencari Group Google PhoneGap untuk istilah "orientasi" .

Salah satu contoh yang saya baca sebagai contoh tentang cara mendeteksi orientasi adalah Pie Guy: ( game , file js ). Ini mirip dengan kode yang Anda kirim, tetapi seperti Anda ... Saya tidak bisa membuatnya berfungsi.

Satu peringatan: eventListener bekerja untuk saya, tapi saya tidak yakin apakah ini pendekatan yang terlalu intensif. Sejauh ini, itulah satu-satunya cara yang berhasil bagi saya, tetapi saya tidak tahu apakah ada cara yang lebih baik dan lebih ramping.


UPDATE memperbaiki kode di atas, sekarang berfungsi


tolong perbaiki nama acara
Dan

5

Saat bekerja dengan orientationchangeacara tersebut, saya membutuhkan batas waktu untuk mendapatkan dimensi elemen yang benar di halaman, tetapi matchMedia bekerja dengan baik. Kode terakhir saya:

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

3

Saya percaya bahwa jawaban yang benar telah diposting dan diterima, namun ada masalah yang saya alami sendiri dan beberapa yang lain telah disebutkan di sini.

Pada platform tertentu, berbagai properti seperti dimensi jendela ( window.innerWidth, window.innerHeight) dan window.orientationproperti tidak akan diperbarui pada saat peristiwa "orientationchange"telah dipecat. Sering kali, properti window.orientationhanya undefinedbeberapa milidetik setelah pemecatan "orientationchange"(setidaknya di Chrome pada iOS).

Cara terbaik yang saya temukan untuk menangani masalah ini adalah:

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

Saya memeriksa untuk melihat apakah orientasinya tidak terdefinisi atau apakah orientasinya sama dengan orientasi terakhir yang terdeteksi. Jika keduanya benar, saya menunggu sepuluh milidetik dan kemudian menguraikan orientasi lagi. Jika orientasi adalah nilai yang tepat, saya memanggil showXOrientationfungsi. Jika orientasi tidak valid, saya terus mengulangi fungsi pemeriksaan saya, menunggu sepuluh milidetik setiap kali, sampai valid.

Sekarang, saya akan membuat JSFiddle untuk ini, seperti yang biasa saya lakukan, tetapi JSFiddle belum bekerja untuk saya dan bug dukungan saya untuk itu ditutup karena tidak ada orang lain yang melaporkan masalah yang sama. Jika ada orang lain yang ingin mengubahnya menjadi JSFiddle, silakan.

Terima kasih! Saya harap ini membantu!


FYI, pada pengujian awal, saya melihat masalah: Saya memutar searah jarum jam beberapa kali dan satu peringatan mengatakan "Orientasi Lansekap: 180" meskipun perangkat saya secara fisik berorientasi sebagai potret.
MarsAndBack

2

inilah yang saya lakukan:

window.addEventListener('orientationchange', doOnOrientationChange);

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

2

Meskipun pertanyaannya hanya merujuk pada penggunaan PhoneGap dan iOS, dan meskipun sudah dijawab, saya dapat menambahkan beberapa poin ke pertanyaan yang lebih luas tentang mendeteksi orientasi layar dengan JS pada tahun 2019:

  1. window.orientationproperti sudah ditinggalkan dan tidak didukung oleh browser Android . Ada properti yang lebih baru yang menyediakan informasi lebih lanjut tentang orientasi - screen.orientation. Tetapi masih eksperimental dan tidak didukung oleh iOS Safari . Jadi untuk mencapai hasil terbaik Anda mungkin perlu menggunakan kombinasi dari dua: const angle = screen.orientation ? screen.orientation.angle : window.orientation.

  2. Seperti @benallansmith sebutkan dalam komentarnya , window.onorientationchangeacara dipecat sebelumnya window.onresize, jadi Anda tidak akan mendapatkan dimensi layar yang sebenarnya kecuali Anda menambahkan beberapa penundaan setelah acara orientasi orientasi.

  3. Ada Plugin Orientasi Layar Cordova untuk mendukung browser seluler yang lebih lama, tetapi saya percaya tidak perlu menggunakannya saat ini.

  4. Ada juga screen.onorientationchangeacara, tetapi sudah usang dan tidak boleh digunakan. Ditambahkan hanya untuk kelengkapan jawaban.

Dalam use case saya, saya tidak terlalu peduli dengan orientasi yang sebenarnya, tetapi lebih pada lebar dan tinggi sebenarnya dari jendela, yang jelas berubah dengan orientasi. Jadi saya menggunakan resizeevent untuk menghindari berurusan dengan penundaan antara orientationchangeevent dan aktualisasi dimensi jendela:

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

Catatan 1: Saya menggunakan sintaks EcmaScript 6 di sini, pastikan untuk mengkompilasinya ke ES5 jika diperlukan.

Catatan 2: window.onresizeacara juga dipicu ketika keyboard virtual diaktifkan , tidak hanya ketika orientasi berubah.


1

Saya menemukan kode ini untuk mendeteksi jika perangkat dalam orientasi lansekap dan dalam kasus ini tambahkan halaman pembuka yang mengatakan "ubah orientasi untuk melihat situs". Ini berfungsi di iOS, android, dan ponsel windows. Saya pikir ini sangat berguna karena cukup elegan dan menghindari untuk menetapkan tampilan lansekap untuk situs seluler. Kode ini bekerja dengan sangat baik. Satu-satunya hal yang tidak sepenuhnya memuaskan adalah bahwa jika seseorang memuat halaman dalam tampilan lanskap halaman splash tidak muncul.

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

Dan 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>


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
    }
}

-2

Berikut ini bekerja untuk saya:

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

Saya membutuhkan batas waktu karena nilai window.orientationtidak memperbarui segera


-3

Saya membuat aplikasi jQTouch di PhoneGap untuk iPhone. Saya telah berjuang dengan masalah ini selama berhari-hari. Saya telah melihat solusi eventlistener yang disarankan beberapa kali, tetapi tidak bisa berfungsi.

Pada akhirnya saya menemukan solusi yang berbeda. Ini pada dasarnya memeriksa lebar tubuh secara berkala menggunakan settimeout. Jika lebarnya 320 maka orientasinya adalah potret, jika 480 maka lansekap. Kemudian, jika orientasi telah berubah sejak pemeriksaan terakhir, itu akan memecat fungsi barang potret atau fungsi barang lanskap di mana Anda dapat melakukan hal Anda untuk setiap orientasi.

Kode (catatan, saya tahu ada beberapa pengulangan dalam kode, hanya belum repot-repot untuk memangkasnya!):

// 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!');
}

8
Pengodean keras perangkat ke 320 atau 480 tidak akan berfungsi di masa depan, atau dengan telepon hi-res saat ini.
Fresheyeball

1
1) Anda harus menggunakan onresizeacara yang akan langsung aktif, bukan dalam 500 milidetik 2) Kode ini khusus untuk android, gunakan onorientationchangesebagai gantinya untuk iPhone 3) Tes jika didukung di browser:"onorientationchange" in window
Dan
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.