Mendeteksi rotasi ponsel Android di browser dengan JavaScript

188

Saya tahu bahwa di Safari pada iPhone Anda dapat mendeteksi orientasi layar dan mengubah orientasi dengan mendengarkan onorientationchangeacara dan menanyakan window.orientationsudutnya.

Apakah ini dimungkinkan di browser di ponsel Android?

Agar lebih jelas, saya bertanya apakah rotasi perangkat Android dapat dideteksi oleh JavaScript yang berjalan pada halaman web standar. Itu mungkin pada iPhone, dan saya bertanya-tanya apakah itu bisa dilakukan untuk ponsel Android.

Philnash
sumber

Jawaban:

214

Untuk mendeteksi perubahan orientasi pada peramban Android, lampirkan pendengar orientationchangeatau resizeacara di 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);

Periksa window.orientationproperti untuk mencari tahu ke arah mana perangkat ini berorientasi. Dengan ponsel Android, screen.widthatau screen.heightjuga pembaruan saat perangkat diputar. (ini tidak terjadi dengan iPhone).

jb.
sumber
apakah ini benar-benar berfungsi? saya mencoba jquery $ (window) .bind ("orientchange", fn); tetapi tidak berhasil, apakah saya harus menggunakan formulir di atas? saya mencoba "perubahan orientasi" di jendela, itu mengembalikan salah
Ayyash
Ini bekerja dengan baik. Ayyash - intinya di sini bahwa ketika "perubahan orientasi" tidak didukung, ia akan kembali ke "mengubah ukuran"
Dror
9
Pada Droid ini benar-benar gila. Ini memperingatkan screen.width 320 ketika ponsel diputar dalam mode lansekap, dan mendeteksi screen.width 569 ketika ponsel diputar dalam mode potret! Bagaimana bisa??
IgorGanapolsky
1
Hanya untuk mengklarifikasi: Mereka yang mencari solusi yang juga berfungsi di iOS harus melihat jawaban dua-bit-bodoh atau saya.
mklement0
3
Tidak perlu menggunakan hack dua-bit-bodoh untuk iOS. Cukup gunakan screen.width dan screen.height di Android dan iOS gunakan window.innerWidth dan window.innerHeight.
Justin
225

Perilaku aktual di berbagai perangkat berbeda tidak konsisten . Acara pengubahan ukuran dan orientasi dapat menyala dalam urutan yang berbeda dengan frekuensi yang bervariasi. Juga, beberapa nilai (mis., Screen.width dan window.orientation) tidak selalu berubah ketika Anda mengharapkannya. Hindari screen.width - tidak berubah saat diputar di iOS.

Pendekatan yang andal adalah mendengarkan acara perubahan ukuran dan orientasi (dengan beberapa polling sebagai tangkapan keselamatan), dan Anda akhirnya akan mendapatkan nilai yang valid untuk orientasi. Dalam pengujian saya, perangkat Android kadang-kadang gagal memecat acara ketika memutar 180 derajat penuh, jadi saya juga menyertakan setInterval untuk polling orientasi.

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

Berikut adalah hasil dari empat perangkat yang telah saya uji (maaf untuk tabel ASCII, tetapi sepertinya cara termudah untuk menyajikan hasilnya). Selain dari konsistensi antara perangkat iOS, ada banyak variasi antar perangkat. CATATAN: Peristiwa terdaftar dalam urutan yang dipecat.

| ================================================= ============================= |
| Perangkat | Acara Dipecat | orientasi | innerWidth | screen.width |
| ================================================= ============================= |
| iPad 2 | mengubah ukuran | 0 | 1024 | 768 |
| (ke lansekap) | perubahan orientasi | 90 | 1024 | 768 |
| ---------------- + ------------------- + ------------ - + ------------ + -------------- |
| iPad 2 | mengubah ukuran | 90 | 768 | 768 |
| (untuk potret) | perubahan orientasi | 0 | 768 | 768 |
| ---------------- + ------------------- + ------------ - + ------------ + -------------- |
| iPhone 4 | mengubah ukuran | 0 | 480 | 320 |
| (ke lansekap) | perubahan orientasi | 90 | 480 | 320 |
| ---------------- + ------------------- + ------------ - + ------------ + -------------- |
| iPhone 4 | mengubah ukuran | 90 | 320 | 320 |
| (untuk potret) | perubahan orientasi | 0 | 320 | 320 |
| ---------------- + ------------------- + ------------ - + ------------ + -------------- |
| Telepon Droid | perubahan orientasi | 90 | 320 | 320 |
| (ke lansekap) | mengubah ukuran | 90 | 569 | 569 |
| ---------------- + ------------------- + ------------ - + ------------ + -------------- |
| Telepon Droid | perubahan orientasi | 0 | 569 | 569 |
| (untuk potret) | mengubah ukuran | 0 | 320 | 320 |
| ---------------- + ------------------- + ------------ - + ------------ + -------------- |
| Samsung Galaxy | perubahan orientasi | 0 | 400 | 400 |
| Tablet | perubahan orientasi | 90 | 400 | 400 |
| (ke lansekap) | perubahan orientasi | 90 | 400 | 400 |
| | mengubah ukuran | 90 | 683 | 683 |
| | perubahan orientasi | 90 | 683 | 683 |
| ---------------- + ------------------- + ------------ - + ------------ + -------------- |
| Samsung Galaxy | perubahan orientasi | 90 | 683 | 683 |
| Tablet | perubahan orientasi | 0 | 683 | 683 |
| (untuk potret) | perubahan orientasi | 0 | 683 | 683 |
| | mengubah ukuran | 0 | 400 | 400 |
| | perubahan orientasi | 0 | 400 | 400 |
| ---------------- + ------------------- + ------------ - + ------------ + -------------- |
dua bit-bodoh
sumber
Di emulator iOS5, jika Anda menyegarkan di lansekap kemudian memutar, kode ini tidak menyala.
bekerja
1
Jawaban yang bagus previousOrientationharus diinisialisasi dengan orientasi saat itu: var previousOrientation = window.orientation;Jika Anda ingin mengabaikan rotasi 180 derajat, yaitu, Anda tidak perlu membedakan antara lanskap kiri atau kanan dan varian terbalik atau tidak, tambahkan yang berikut sebagai baris pertama ke checkOrientation(): if (0 === (previousOrientation + window.orientation) % 180) return;Namun, tanpa setTimeouttipu daya tambahan , Anda hanya akan mendapat manfaat dari ini di iOS, di mana rotasi 180 derajat yang cepat hanya menciptakan satu orientationchange peristiwa.
mklement0
Terima kasih @mklement, saya mengubah kode untuk menginisialisasi sebelumnya.
dua-bit-bodoh
Sorakan untuk informasi hebat. Ini membuat kepala saya masuk karena windows phone 8.1 tidak menampilkan perubahan ukuran atau orientasi perubahan acara ketika Anda menggunakan cordova. Dipaksa menggunakan setInterval juga sebagai failafe.
Kesempurnaan
@ mklement0 Sampai hari ini window.orientation akan selalu ditentukan pada windows phone 8.1.
Kesempurnaan
39

jawaban dua-bit-bodoh yang sangat baik memberikan semua latar belakang, tetapi biarkan saya mencoba ringkasan, pragmatis singkat tentang bagaimana menangani perubahan orientasi di iOS dan Android :

  • Jika Anda hanya peduli pada dimensi jendela (skenario tipikal) - dan bukan tentang orientasi spesifik:
    • Tangani resizeacara saja.
    • Di pawang Anda, bertindaklah window.innerWidthdan lakukan window.InnerHeightsaja.
    • JANGAN gunakan window.orientation- ini tidak akan saat ini di iOS.
  • Jika Anda Peduli dengan orientasi spesifik :
    • Menangani hanya satu resizeacara pada Android, dan hanya satu orientationchangeacara di iOS.
    • Di handler Anda, aktifkan window.orientation(dan window.innerWidthdan window.InnerHeight)

Pendekatan ini menawarkan sedikit manfaat daripada mengingat orientasi sebelumnya dan membandingkan:

  • pendekatan dimensi saja juga berfungsi saat berkembang pada browser desktop yang dapat mensimulasikan perangkat seluler, misalnya, Chrome 23. ( window.orientationtidak tersedia di browser desktop).
  • tidak perlu untuk variabel tingkat global / anonim-file-fungsi-wrapper-level.
mklement0
sumber
Masalahnya adalah bahwa ketika mengubah ukuran atau acara orientasi menembakkan window.innerWidth melaporkan perangkat yang salah dan Droid
albanx
@albanx yang masih menjadi masalah di chrome pada ios: / safari baik-baik saja
oldboy
12

Anda selalu dapat mendengarkan acara pengubahan ukuran jendela. Jika, pada kejadian itu, jendelanya berubah dari lebih tinggi daripada lebar menjadi lebih lebar daripada tinggi (atau sebaliknya), Anda dapat yakin orientasi telepon baru saja diubah.

Joel Mueller
sumber
Itu ide yang bagus, saya akan coba itu (dan tanyakan teman saya dengan ponsel Android untuk menguji!)
philnash
Saya baru menyadari bahwa metode ini tidak memberi saya orientasi pada ponsel. Saya akan tahu apakah itu potret atau lanskap, tetapi tidak jika terbalik atau diputar ke kiri atau ke kanan. Ada ide lebih lanjut?
philnash
Saya tidak yakin bagaimana ini bisa menjadi masalah ... Mengapa Anda perlu tahu apakah teleponnya terbalik? Browser ponsel memiliki bagian atas, dan halaman web akan berorientasi ke bagian atas browser. Setiap pengguna dengan dua sel-sel otak untuk menggosok bersama-sama siapa yang melihat halaman web terbalik hanya akan mengubah telepon mereka sekitar jika mereka ingin melihatnya sisi kanan-up
Joel Mueller
1
Itu agak kasar. Saya tertarik untuk mengetahui sehingga saya dapat menampilkan konten yang berbeda berdasarkan orientasi layar, ini bisa sampai 4 halaman yang berbeda, membutuhkan browser untuk mengetahui apakah telah diputar dengan 0, 90, 180 dan 270 derajat. Ini semua mungkin, dalam JavaScript, di iPhone dan itulah sebabnya saya bertanya.
philnash
Saya masih kesulitan membayangkan apa yang bisa dilakukan halaman web secara berbeda ketika perangkat yang digunakan diputar 270 derajat, tetapi jika Anda mengatakan Anda memiliki case-use yang valid, saya tidak akan berdalih. Dalam hal ini: Maaf, tetapi saya tidak tahu apakah peramban Android memberikan tingkat detail seperti ini.
Joel Mueller
3

Itu mungkin dalam HTML5.
Anda dapat membaca lebih lanjut (dan coba demo langsung) di sini: http://slides.html5rocks.com/#slide-orientation .

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

Ini juga mendukung browser deskop tetapi akan selalu mengembalikan nilai yang sama.

Derek 朕 會 功夫
sumber
4
Acara ini benar-benar lebih untuk akses ke sensor gerak, meskipun saya kira itu juga dapat digunakan untuk mendeteksi perubahan orientasi.
René
Pada Android Galaxy S2 saya itu tidak didukung pada browser saham atau Browser Dolphin. Tetapi berfungsi baik dengan mobile firefox.
Eduardo
3

Saya memiliki masalah yang sama. Saya menggunakan Phonegap dan Jquery mobile, untuk perangkat Adroid. Untuk mengubah ukuran dengan benar, saya harus mengatur batas waktu:

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

Ini solusinya:

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
sumber
Ini adalah solusi yang paling cocok untuk saya, saya tahu ini tidak 100% akurat tetapi Anda dapat mendeteksi horizontal vs vertikal menggunakan ini: var screenWidth = $ (window) .width (); var screenHeight = $ (window) .height (); if (screenWidth> screenHeight) {doSomething (); }
math0ne
Yang ini adalah solusi bagi saya di tablet Android jelek. window.onresize, attachevent dan addeventlistener gagal pada beberapa event (resize, onresize, perubahan orientasi, orientasi perangkat). Hanya Jquery $ (jendela) .on () yang berfungsi.
Lego
1

Gotcha lain - beberapa tablet Android (Motorola Xoom yang saya percaya dan Elonex low-end yang saya coba beberapa pengujian, mungkin juga yang lain) memasang accelerometer sehingga window.orientation == 0 dalam mode LANDSCAPE, bukan potret !

james-geldart
sumber
1

Anda dapat mencoba solusinya, kompatibel dengan semua browser.

Berikut ini adalah orientationchangegambar kompatibilitas: kesesuaian oleh karena itu, saya membuat orientaionchangepolyfill, ini berdasarkan pada atribut @media untuk memperbaiki pustaka orientasichangechange—— orientasichange-fix

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

Perlu dicatat bahwa pada Epic 4G Touch saya, saya harus mengatur tampilan web untuk menggunakan WebChromeClient sebelum salah satu panggilan android javascript bekerja.

webView.setWebChromeClient(new WebChromeClient());
calebisstupid
sumber
0

Cara lintas browser

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

Sedikit kontribusi untuk jawaban dua-bit-bodoh:

Seperti yang dijelaskan pada tabel pada ponsel "acara perubahan orientasi" dipecat lebih awal dari peristiwa "mengubah ukuran" sehingga memblokir panggilan perubahan ukuran berikutnya (karena pernyataan if). Properti lebar masih belum ditetapkan.

Sebuah solusi meskipun mungkin bukan yang sempurna bisa dengan tidak memecat acara "orientasi perubahan". Itu bisa diarsipkan dengan membungkus acara "orientasi perubahan" yang mengikat pernyataan "jika":

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

Semoga ini bisa membantu

(tes dilakukan pada Nexus S)

Alex
sumber