Android'de düzende yön değişikliği nasıl tespit edilir?


110

Sadece bir yön değiştirme özelliği uyguladım - örneğin, düzen dikeyden yataya (veya tam tersi) değiştiğinde. Oryantasyon değişikliği etkinliğinin bittiğini nasıl tespit edebilirim.

OrientationEventListenerÇalışma yoktu. Düzen yönü değişikliği olayları hakkında nasıl bildirim alabilirim?


Benim durumumda, yön değiştiğinde onCreate () çağrıldı.
Josiel Novaes

Yanıtlar:


293

OnConfigurationChanged Activity yöntemini kullanın . Aşağıdaki koda bakın:

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    // Checks the orientation of the screen
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
        Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
    }
}

Ayrıca uygun olanı düzenlemelisiniz. Android: configChanges eklemek için manifest dosyanızdaki öğesi Sadece aşağıdaki koda bakın:

<activity android:name=".MyActivity"
          android:configChanges="orientation|keyboardHidden"
          android:label="@string/app_name">

NOT: Android 3.2 (API seviyesi 13) veya üzeri sürümlerde, "ekran boyutu" da cihaz dikey ve yatay yön arasında geçiş yaptığında değişir. Bu nedenle, API seviyesi 13 veya üstü için geliştirme yaparken yön değişikliği nedeniyle çalışma zamanının yeniden başlatılmasını önlemek istiyorsanız, API seviyesi 13 veya üstü için android: configChanges = "orientation | screenSize" beyan etmeniz gerekir .

Umarım bu size yardımcı olur ... :)


3
Bu iyidir, ancak layout xml'i layout-land klasörüne yüklerken, dikey xml layout dosyalarını kullanır.
Programcı

23
Aztec Coder, "android: configChanges =" orientation "eklediğinizde, oryantasyon değişikliğini idare edeceğinizi beyan etmiş olursunuz, bu da manzaraya geçtiğinizde etkinliğinizin yeniden oluşturulmayacağı anlamına gelir. Bunun yerine, onConfigurationChanged çağrılır. Bu istenmiyorsa , aktivitenizin yönünü hatırlamak için bir değişken kullanabilirsiniz ve her seferinde Duraklat'a (örneğin) gidip oryantasyonun hala aynı olup olmadığını kontrol edebilirsiniz.
Elena

14
API seviyesi 13 (3.2) veya üzeri için geliştirme yapıyorsanız android: configChanges = "orientation | screenSize" belirtmelisiniz, aksi takdirde onConfigurationChanged çağrılmaz: developer.android.com/guide/topics/resources/…
Arne

1
Merhaba, uygulamamı API 10 (Android 2.3.3) ile oluşturuyorum. Ve android: configChanges = "orientation | keyboardHidden" kullandığımda yönlendirmeyi mükemmel bir şekilde tanıyor. Ancak Android 4.1.2 çalıştıran Nexus S cihazım yön değişikliğini algılamıyor, ne yapmalıyım?
Karthik Andhamil

2
Kullanım android: configChanges = | "oryantasyon Screensize" yerine android ait: configChanges = "oryantasyon | keyboardHidden" Manifest'inizde dosya ve kontrol altında ... !!!
Dinesh Sharma

15

Düzeni layout-land klasörüne yüklemek için iki ayrı düzene sahip olduğunuz ve setContentViewardından onConfigurationChangedyöntemde yapmanız gerektiği anlamına gelir .

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    // Checks the orientation of the screen
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        setContentView(R.layout.yourxmlinlayout-land);
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
        setContentView(R.layout.yourxmlinlayoutfolder);
    }
}

Yalnızca bir düzeniniz varsa, bu yöntemde setContentView yapmak gerekmez. basitçe

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
}

19
Geçersiz kılmak yerine layout / main.xml ve layout-land / main.xml'yi kullanın.
Jared Burrows


Bir ekran rotasyonu nedeniyle etkinliğimin sonlandırıldığını tespit etmek istedim. onConfigurationChanged(Configuration newConfig)Yöntemi uyguladım (bu cevapta olduğu gibi), ancak onu kendim ele almak yerine, bir Boole bayrağı belirledim ve ardından recreate()Android'in etkinliği normal şekilde yeniden oluşturması için yöntemi çağırdım .
sersemlemiş

recreate()Yöntemle ilgili bir sorun , ekranın kısa bir süre siyah yanıp sönmesine neden olmasıdır. Bu nedenle başka bir yaklaşım kullandım: (1) ekran genişliğini kaydedin onCreate(...), (2) aktivite sonlandırılırken herhangi bir yaşam döngüsü yönteminde kaydedilen ekran genişliğini mevcut ekran genişliğiyle karşılaştırın (örneğin onSaveInstanceState(...)).
sersemlemiş

13

Sadece onConfigurationChanged sonrasında tüm Bundle'ınızı kaydetmenin bir yolunu göstermek istedim:

Dersten hemen sonra yeni Paket oluşturun:

public class MainActivity extends Activity {
    Bundle newBundy = new Bundle();

Sonra, "korumalı void onCreate" sonrasına şunu ekleyin:

@Override
public void onConfigurationChanged(Configuration newConfig) {
     super.onConfigurationChanged(newConfig);
     if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            onSaveInstanceState(newBundy);
        } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
            onSaveInstanceState(newBundy);
        }
}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putBundle("newBundy", newBundy);
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    savedInstanceState.getBundle("newBundy");
}

Bunu eklerseniz, tüm kasalı sınıflarınız MainActivity'ye kaydedilir.

Ancak en iyi yol, bunu AndroidManifest'inize eklemektir:

<activity name= ".MainActivity" android:configChanges="orientation|screenSize"/>

7
Bu yanıltıcıdır. Uygulama onConfigurationChanged(), yönlendirme değiştiğinde instanceState'inizin yok edilmemesi için onu kaydetmenize gerek kalmaması için yapar. Etkinlik yaşam döngüsündeki diğer etkinlikler için kaydetmek isteyebilirsiniz, ancak bilmiyorum.
izzy

5

bu yöntemi kullan

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT)
    {
        Toast.makeText(getActivity(),"PORTRAIT",Toast.LENGTH_LONG).show();
       //add your code what you want to do when screen on PORTRAIT MODE
    }
    else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE)
    {
        Toast.makeText(getActivity(),"LANDSCAPE",Toast.LENGTH_LONG).show();
        //add your code what you want to do when screen on LANDSCAPE MODE
   }
}

Ve bunu Androidmainfest.xml dosyanıza eklemeyi unutmayın.

android:configChanges="orientation|screenSize"

bunun gibi

<activity android:name=".MainActivity"
          android:theme="@style/Theme.AppCompat.NoActionBar"
          android:configChanges="orientation|screenSize">

    </activity>

2

Etkinliğin yöntemini onConfigurationChanged geçersiz kıl


Bildirimdeki <activity> etiketinin içinde aşağıdaki satır olmadan, onConfigurationChanged () geri çağrısının tetiklenmeyeceğini belirtmek isterim. android: configChanges = "orientation"
Sreekanth Karumanaghat

1

Yukarıda açıklandığı gibi, gerçekten bazılarınızı ilgilendirecek başka bir alternatif önermek istiyorum:

android:configChanges="orientation|keyboardHidden" 

enjekte edilecek düzeni açıkça beyan ettiğimizi ima eder.

Düzen-arazi ve yerleşim klasörleri sayesinde otomatik enjeksiyonu korumak istememiz durumunda. Tek yapmanız gereken onu onCreate'e eklemek:

    if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
        getSupportActionBar().hide();

    } else if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
        getSupportActionBar().show();
    }

Burada, telefonun yönüne bağlı olarak işlem çubuğunu görüntüleyip görüntülemiyoruz


0

Bir OrientationEventListenersınıf örneği oluşturun ve etkinleştirin.

OrientationEventListener mOrientationEventListener = new OrientationEventListener(YourActivity.this) {
    @Override
    public void onOrientationChanged(int orientation) {
        Log.d(TAG,"orientation = " + orientation);
    }
};

if (mOrientationEventListener.canDetectOrientation())
    mOrientationEventListener.enable();

2
Lütfen cevabınızı bozmayın. Silmek isterseniz, cevabınızın sol alt kısmında sil düğmesini bulabilirsiniz.
CalvT

0

Kabul edilen yanıt sizin için işe yaramazsa, manifest dosyasında tanımlamadığınızdan emin olun:

android:screenOrientation="portrait"

Benim durumum bu.


0

Bu, yukarıda belirtilmediği için bazı yeni geliştiricilerin kullanması durumunda. Sadece çok açık olmak gerekirse:

OnConfigurationChanged kullanıyorsanız iki şeye ihtiyacınız vardır :

  1. onConfigurationChangedAktivite Sınıfınızdaki bir yöntem

  2. Bildiriminizde , yönteminiz tarafından hangi yapılandırma değişikliklerinin ele alınacağını belirtinonConfigurationChanged

Yukarıdaki yanıtlardaki manifest snippet'i, manifestin ait olduğu belirli uygulama için doğru olsa da, Aktivite Sınıfınızdaki onConfigurationChanged yöntemini tetiklemek için bildiriminize tam olarak eklemeniz gereken şey DEĞİLDİR . ör. aşağıdaki manifest girişi uygulamanız için doğru olmayabilir.

<activity name= ".MainActivity" android:configChanges="orientation|screenSize"/>

Yukarıdaki bildirim girişinde, aşağıdakiler için çeşitli Android eylemleri vardır: android:configChanges="" Etkinlik yaşam döngünüzde onCreate'i tetikleyebilecek .

Bu çok önemlidir - Manifestte Belirtilmeyenler onConfigurationChangedonCreate'inizi tetikleyenlerdir ve manifestte belirtilenler Aktivite Sınıfınızdaki metodunuzu tetikleyenlerdir .

Bu nedenle, hangi yapılandırma değişikliklerini kendiniz halletmeniz gerektiğini belirlemeniz gerekir. Benim gibi Ansiklopedik Olarak Meydan Okuyan Android için, Android Studio'daki hızlı ipuçlarını kullandım ve hemen hemen her olası yapılandırma seçeneğine ekledim. Bunların hepsini listelemek temelde her şeyi halledeceğimi ve onCreate'in yapılandırmalar nedeniyle asla çağrılmayacağını söyledi.

<activity name= ".MainActivity" android:configChanges="screenLayout|touchscreen|mnc|mcc|density|uiMode|fontScale|orientation|keyboard|layoutDirection|locale|navigation|smallestScreenSize|keyboardHidden|colorMode|screenSize"/>

Açıkçası her şeyi halletmek istemiyorum, bu yüzden yukarıdaki seçenekleri teker teker kaldırmaya başladım. Her kaldırma işleminden sonra uygulamamı yeniden oluşturma ve test etme.

Bir başka önemli nokta : onCreate'inizi tetikleyen otomatik olarak işlenen tek bir yapılandırma seçeneği varsa (yukarıdaki bildiriminizde listelenmemişse), o zaman şu şekilde görünecektir:onConfigurationChanged çalışmıyor . Tüm ilgili olanları manifestinize koymalısınız.

Başlangıçta onCreate'i tetikleyen 3 ile bitirdim, sonra bir S10 + üzerinde test ettim ve hala onCreate'i alıyordum, bu yüzden eleme egzersizimi tekrar yapmak zorunda kaldım ve ayrıca |screenSize. Bu nedenle, çeşitli platformlarda test edin.

<activity name= ".MainActivity" android:configChanges="screenLayout|uiMode|orientation|screenSize"/>

Öyleyse benim önerim, eminim ki birisi bunda delikler açabilir:

  1. onConfigurationChangedMetodunuzu bir TOAST veya LOG ile Aktivite Sınıfınıza ekleyin, böylece ne zaman çalıştığını görebilirsiniz.

  2. Bildiriminize tüm olası yapılandırma seçeneklerini ekleyin.

  3. onConfigurationChangedUygulamanızı test ederek yönteminizin çalıştığını doğrulayın .

  4. Her yapılandırma seçeneğini manifest dosyanızdan teker teker kaldırın ve uygulamanızı her seferinde test edin.

  5. Mümkün olduğunca çok çeşitli cihazlarda test edin.

  6. Yukarıdaki snippet'imi manifest dosyanıza kopyalamayın / yapıştırmayın. Android güncellemeleri listeyi değiştirir, bu nedenle hepsini aldığınızdan emin olmak için açılır Android Studio ipuçlarını kullanın.

Umarım bu birisine biraz zaman kazandırır.

Benim onConfigurationChangedhemen altında bilgi için yöntem. yeni yönlendirme mevcut olduktan sonra , ancak kullanıcı arayüzü yeniden oluşturulmadan önceonConfigurationChanged yaşam döngüsünde çağrılır . Bu nedenle , yönlendirmeyi ilk kontrol eden benim doğru çalışıyor ve ardından UI ImageView'umun görünürlüğüne bakmak için iç içe geçmiş 2 de doğru çalışıyor.ifif

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);

        // Checks the orientation of the screen
        if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            pokerCardLarge = findViewById(R.id.pokerCardLgImageView);

            if(pokerCardLarge.getVisibility() == pokerCardLarge.VISIBLE){
                Bitmap image = ((BitmapDrawable)pokerCardLarge.getDrawable()).getBitmap();
                pokerCardLarge.setVisibility(pokerCardLarge.VISIBLE);
                pokerCardLarge.setImageBitmap(image);
            }

        } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
            pokerCardLarge = findViewById(R.id.pokerCardLgImageView);

            if(pokerCardLarge.getVisibility() == pokerCardLarge.VISIBLE){
                Bitmap image = ((BitmapDrawable)pokerCardLarge.getDrawable()).getBitmap();
                pokerCardLarge.setVisibility(pokerCardLarge.VISIBLE);
                pokerCardLarge.setImageBitmap(image);
            }

        }
    }

0

en basit biçimde Kotilin uygulaması için - yalnızca ekran dikey <--> yataydan değiştiğinde tetiklenir, cihaza bir çevirme algılamasına (180 derece) ihtiyacınız varsa, yerçekimi sensörü değerlerine girmeniz gerekir

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

val rotation = windowManager.defaultDisplay.rotation

    when (rotation) {            
        0 -> Log.d(TAG,"at zero degree")
        1 -> Log.d(TAG,"at 270 degree")
        2 -> Log.d(TAG,"at 180 degree")
        3 -> Log.d(TAG,"at 90 degree")


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