JavaScript ile Android telefonun tarayıcıdaki dönüşünü algılama


188

Bir iPhone'daki Safari'de, onorientationchangeolayı dinleyerek window.orientationve açıyı sorgulayarak ekranın yönünü ve yön değişikliğini algılayabileceğinizi biliyorum .

Bu, Android telefonlardaki tarayıcıda mümkün mü?

Açık olmak gerekirse, bir Android cihazının rotasyonunun standart bir web sayfasında çalışan JavaScript tarafından tespit edilip edilemeyeceğini soruyorum . Bir iPhone'da mümkün ve Android telefonlar için yapılıp yapılamayacağını merak ettim.

Yanıtlar:


214

Android tarayıcıda bir yönlendirme değişikliği saptamak için şu adrese orientationchangeveya resizeetkinliğe bir dinleyici ekleyin 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);

window.orientationCihazın hangi yöne yönlendirildiğini anlamak için özelliği kontrol edin . Android telefonlarda screen.widthveya screen.heightcihaz döndürüldüğünde güncellenir. (iPhone'da durum böyle değil).


bu gerçekten işe yarıyor mu? jquery $ (pencere) .bind ("orientationchange", fn) denedim; ama işe yaramadı, yukarıdaki formu kullanmak zorunda mıyım? pencerede "onorientationchange" denedim, yanlış retuns
Ayyash

İyi çalışıyor. Ayyash - "oryantasyon değişimi" desteklenmediği zaman "yeniden boyutlandırmak" için geri düşecek tüm nokta
Dror

9
Droid'de bu tamamen çılgınca. Telefon yatay modda döndürüldüğünde 320. genişlik uyarısı verir ve telefon dikey modda döndürüldüğünde ekran genişliğini algılar! Nasıl olur??
IgorGanapolsky

1
Açıklığa kavuşturmak için: iOS'ta da çalışan bir çözüm arayanlar iki bit aptalı veya cevabımı incelemelidir.
mklement0

3
İOS için iki bit aptal kesmek kullanmaya gerek yok. Sadece Android ve iOS'ta screen.width ve screen.height kullanın window.innerWidth ve window.innerHeight kullanın.
Justin

225

Farklı aygıtlar arasındaki gerçek davranış tutarsız . Resize ve orientationChange olayları, değişen sıklıkta farklı bir sırada tetiklenebilir. Ayrıca, bazı değerler (örn. Screen.width ve window.orientation) beklediğinizde her zaman değişmez. Screen.width'den kaçının - iOS'ta döndürürken değişmez.

Güvenilir yaklaşım, hem yeniden boyutlandırma hem de yönlendirme dinlemektir Olayları değiştirin (bazıları güvenlik yakalama olarak yoklama ile) ve sonunda yönlendirme için geçerli bir değer elde edersiniz. Testlerimde, Android cihazlar bazen tam 180 derece döndürürken olayları tetikleyemedi, bu yüzden yönlendirmeyi yoklamak için bir setInterval ekledim.

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

İşte test ettiğim dört cihazdan sonuçlar (ASCII tablosu için özür dilerim, ancak sonuçları sunmanın en kolay yolu gibi görünüyordu). İOS cihazlar arasındaki tutarlılığın yanı sıra, cihazlar arasında çok çeşitli var. NOT: Olaylar tetiklendikleri sırayla listelenir.

| ================================================= ============================= |
| Cihaz | Yapılan Etkinlikler | yönlendirme | innerWidth | screen.width |
| ================================================= ============================= |
| iPad 2 | yeniden boyutlandırma | 0 | 1024 | 768 |
| (manzaraya) | oryantasyon değişimi | 90 | 1024 | 768 |
| ---------------- + ------------------- + ------------ - + ------------ + -------------- |
| iPad 2 | yeniden boyutlandırma | 90 | 768 | 768 |
| (portreye) | oryantasyon değişimi | 0 | 768 | 768 |
| ---------------- + ------------------- + ------------ - + ------------ + -------------- |
| iPhone 4 | yeniden boyutlandırma | 0 | 480 | 320 |
| (manzaraya) | oryantasyon değişimi | 90 | 480 | 320 |
| ---------------- + ------------------- + ------------ - + ------------ + -------------- |
| iPhone 4 | yeniden boyutlandırma | 90 | 320 | 320 |
| (portreye) | oryantasyon değişimi | 0 | 320 | 320 |
| ---------------- + ------------------- + ------------ - + ------------ + -------------- |
| Droid telefon | oryantasyon değişimi | 90 | 320 | 320 |
| (manzaraya) | yeniden boyutlandırma | 90 | 569 | 569 |
| ---------------- + ------------------- + ------------ - + ------------ + -------------- |
| Droid telefon | oryantasyon değişimi | 0 | 569 | 569 |
| (portreye) | yeniden boyutlandırma | 0 | 320 | 320 |
| ---------------- + ------------------- + ------------ - + ------------ + -------------- |
| Samsung Galaxy | oryantasyon değişimi | 0 | 400 | 400 |
| Tablet | oryantasyon değişimi | 90 | 400 | 400 |
| (manzaraya) | oryantasyon değişimi | 90 | 400 | 400 |
| | yeniden boyutlandırma | 90 | 683 | 683 |
| | oryantasyon değişimi | 90 | 683 | 683 |
| ---------------- + ------------------- + ------------ - + ------------ + -------------- |
| Samsung Galaxy | oryantasyon değişimi | 90 | 683 | 683 |
| Tablet | oryantasyon değişimi | 0 | 683 | 683 |
| (portreye) | oryantasyon değişimi | 0 | 683 | 683 |
| | yeniden boyutlandırma | 0 | 400 | 400 |
| | oryantasyon değişimi | 0 | 400 | 400 |
| ---------------- + ------------------- + ------------ - + ------------ + -------------- |

İOS5 öykünücüsünde, manzarada yenilenir ve sonra döndürürseniz, bu kod tetiklenmez.
çalıştı

1
Mükemmel cevap. previousOrientationo zaman geçerli yönlendirmeyle başlatılmalıdır: var previousOrientation = window.orientation;180 derecelik dönüşleri yok saymak istiyorsanız, yani, sol veya sağ manzara ile baş aşağı veya yukarı değişkenleri birbirinden ayırmanız gerekmez, aşağıdakileri ekleyin ilk satır olarak checkOrientation(): if (0 === (previousOrientation + window.orientation) % 180) return;Ancak, ek setTimeouthile olmadan , sadece 180 derecelik hızlı bir dönüşün tek bir orientationchange etkinlik oluşturduğu iOS'ta bundan yararlanacaksınız .
mklement0

Teşekkürler mklement, önceki Yönlendirmeyi başlatmak için kodu değiştirdim.
iki bit aptal

Büyük bilgi için şerefe. Bu benim kafamda yapıyordu çünkü windows phone 8.1, cordova kullandığınızda yeniden boyutlandırma veya yön değiştirme olayı içermiyor. SetInterval ve arıza güvenliği olarak kullanıldı.
Mükemmellik

@ mklement0 Bu güne kadar window.orientation her zaman Windows 8.1 telefonunda tanımsız olacaktır.
Mükemmellik

39

iki bit aptalın mükemmel yanıtı tüm arka planı sağlar, ancak iOS ve Android'de yön değişikliklerini nasıl ele alacağınıza dair kısa ve pragmatik bir özet sunmaya çalışalım :

  • Belirli pencere yönünü değil , yalnızca pencere boyutlarını (tipik senaryo) önemsiyorsanız :
    • Kulp resizeolayı sadece.
    • İşleyicinizde sadece window.innerWidthve window.InnerHeightsadece harekete geçin .
    • KULLANMAYIN window.orientation- iOS'ta güncel olmayacaktır.
  • Belirli bir yönü önemsiyorsanız :
    • Kulp sadeceresize Android'de olayı ve sadeceorientationchange iOS'da olayı.
    • İşleyicinizde harekete geçin window.orientation(ve window.innerWidthve window.InnerHeight)

Bu yaklaşımlar, önceki yönelimi hatırlamak ve karşılaştırmaktan biraz fayda sağlar:

  • yalnızca boyutlar yaklaşımı, mobil cihazları, örneğin Chrome 23'ü ( window.orientationmasaüstü tarayıcılarda kullanılamaz) simüle edebilen masaüstü tarayıcılarda geliştirirken de çalışır .
  • genel / anonim dosya-düzeyi-işlev-sarmalayıcı düzeyi değişkenine gerek yoktur.

Sorun, yeniden boyutlandırma veya yönlendirme olayı
pencereyi tetiklediğinde. İnnerWidth

@albanx, ios'ta hala kromda bir sorun: / safari is fine tho
oldboy

12

Pencere yeniden boyutlandırma olayını her zaman dinleyebilirsiniz. Bu olayda, pencere uzun boylu olmaktan uzun boylu olmaktan uzun boylu olmaktan geniş (veya tam tersi) olursa, telefon yönünün değiştiğinden emin olabilirsiniz.


Bu iyi bir fikir, bunu deneyeceğim (ve Android telefonla arkadaşımdan test etmesini isteyeceğim!)
philnash

Bu yöntemin bana telefonun yönünü vermediğini fark ettim. Dikey mi yoksa manzara mı olduğunu bileceğim, ancak baş aşağı mı yoksa sola mı yoksa sağa mı döndürüldüğünü bilemeyeceğim. Başka fikir var mı?
philnash

Bunun ne kadar önemli olabileceğinden emin değilim ... Telefonun ters olup olmadığını neden bilmelisin? Telefonun tarayıcısının bir üst kısmı vardır ve web sayfası tarayıcının üst tarafına yönlendirilir. Bir web sayfasına baş aşağı bakan iki beyin hücresi olan her kullanıcı, sağ tarafını görmek isterse telefonunu ters
çevirir

1
Bu biraz sert. Ekranın yönüne bağlı olarak farklı içerik gösterebilmem için biliyorum, bu 4 farklı sayfaya kadar olabilir ve tarayıcının 0, 90, 180 ve 270 derece döndürülüp döndürülmediğini bilmesini gerektirir. Tüm bunlar, JavaScript'te, iPhone'da mümkündür ve bu yüzden soruyorum.
philnash

Bir web sayfasının, oluşturulduğu cihaz 270 derece döndürüldüğünde, farklı bir şekilde neler yapabileceğini hayal etmekte hala zorlanıyorum, ancak geçerli bir kullanım durumunuz olduğunu söylüyorsanız, tartışmayacağım. Bu durumda: Üzgünüm, ancak Android tarayıcısının bu düzeyde ayrıntı sağlayıp sağlamadığını bilmiyorum.
Joel Mueller

3

HTML5'te mümkündür.
Buradan daha fazla bilgi edinebilir (ve canlı bir demo deneyebilirsiniz): http://slides.html5rocks.com/#slide-orientation .

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

Ayrıca masaüstü tarayıcılarını da destekler, ancak her zaman aynı değeri döndürür.


4
Bu olay hareket sensörlerine erişim için gerçekten daha fazla olsa da, yönelim değişikliğini tespit etmek için de kullanılabileceğini düşünüyorum.
René

Android Galaxy S2 cihazımda stok tarayıcıda veya Dolphin Tarayıcı'da desteklenmiyor. Ancak mobil firefox ile iyi çalışır.
Eduardo

3

Ben de aynı problemi yaşadım. Adroid cihazları için Phonegap ve Jquery mobile kullanıyorum. Doğru şekilde yeniden boyutlandırmak için bir zaman aşımı ayarlamalıydım:

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

İşte çözüm:

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

Bu benim için en iyi çözüm, onun% 100 doğru olmadığını biliyorum ama bunu kullanarak yatay vs dikey tespit edebilirsiniz: var screenWidth = $ (window) .width (); var screenHeight = $ (pencere) .height (); if (screenWidth> screenHeight) {doSomething (); }
math0ne

Bu, berbat bir Android tablette benim için bir çözümdü. window.onresize, attachevent ve addeventlistener birden fazla olayda başarısız oldu (yeniden boyutlandırma, yeniden boyutlandırma, yön değiştirme, geliştirme). Sadece Jquery $ (window) .on () çalıştı.
Lego

1

Başka bir gotcha - bazı Android tabletler (inandığım Motorola Xoom ve üzerinde bazı testler yaptığım düşük seviye Elonex biri, muhtemelen diğerleri de) ivmeölçerleri ayarlandı, böylece pencere değil. Oryantasyon == 0 LANDSCAPE modunda, portre değil !


1

tüm tarayıcılarla uyumlu çözümü deneyebilirsiniz.

Aşağıda orientationchangeuyumluluk resmi: uygunluk bu nedenle, bir yazar orientaionchangepolyfill bir düzeltme orientationChange, kuruluşun library-- için @media öznitelik dayanmaktadır orientationChange-fix

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

0

Epic 4G Touch cihazımda, herhangi bir javascript android çağrısı işe başlamadan önce WebChromeClient'i kullanmak için web görünümünü ayarlamak zorunda olduğumu belirtmek gerekir.

webView.setWebChromeClient(new WebChromeClient());

0

Çapraz tarayıcı yolu

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

-1

İki bit aptalın cevabına küçük bir katkı:

Droid telefonları tabloda açıklandığı gibi "orientationchange" olayı "resize" olayından daha önce tetiklenir, böylece bir sonraki yeniden boyutlandırma çağrısını engeller (if ifadesi nedeniyle). Width özelliği hala ayarlanmadı.

Mükemmel bir çözüm olmasa da bir çözüm "orientationchange" olayını tetiklememek olabilir. Bu, "if" deyimindeki "orientationchange" olay bağlama sarmalanarak arşivlenebilir:

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

Umarım yardımcı olur

(testler Nexus S üzerinde yapıldı)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.