Rotasyon Android'de etkinlik yeniden başlatma


1379

Android uygulamamda, cihazı döndürdüğümde (klavyeyi dışarı kaydırdığımda) Activityyeniden başlatılır ( onCreateçağrılır). Şimdi, bu muhtemelen böyle olması gerekiyordu, ama ben onCreateyöntemde ilk kurulum bir sürü yapmak , bu yüzden ya gerek:

  1. Başlangıçtaki tüm ayarları başka bir fonksiyona yerleştirin, böylece cihaz rotasyonunda veya
  2. Bunu onCreatetekrar çağırmayın ve düzen sadece ayarlar veya
  3. Uygulamayı çağırmamak için sadece portre ile onCreatesınırlandırın.

4
Bu blog yazısında etkinlik yapılandırması değişiklikleri sırasında uzun süredir eşzamansız görevlerin nasıl tutulacağına dair oldukça eksiksiz bir açıklama var !
Adrian Monk

3
Diğerlerinin zaten cevapladığı gibi bu doğrudan bir cevap değil, ancak yaşam döngülerine ilişkin android uygulamalarınızda neler olduğunu anlamak için LogLifeCycle'a bir göz atmaya davet ediyorum .
Snicolas

Yanıtlar:


965

Uygulama Sınıfını Kullanma

Başlatma işleminizde ne yaptığınıza bağlı olarak Application, başlatma kodunuzu genişleten ve onCreatebu sınıf içindeki geçersiz kılınmış bir yönteme taşıyan yeni bir sınıf oluşturmayı düşünebilirsiniz .

public class MyApplicationClass extends Application {
  @Override
  public void onCreate() {
    super.onCreate();
    // TODO Put your application initialization code here.
  }
}

onCreateTüm uygulama oluşturulduğunda yönelim veya klavye görünürlük değişiklikleri Etkinlik yeniden başlatıldığında o tetiklememeleri için başvuru sınıftaki tek çağrılır.

Bu sınıfın örneğini tekil olarak göstermek ve alıcıları ve ayarlayıcıları kullanarak başlattığınız uygulama değişkenlerini ortaya çıkarmak iyi bir uygulamadır.

NOT: Yeni Uygulama sınıfınızın, kaydedilmesi ve kullanılması için manifest'te adını belirtmeniz gerekir:

<application
    android:name="com.you.yourapp.MyApplicationClass"

Yapılandırma Değişikliklerine Tepki [UPDATE: API 13'ten beri kullanımdan kaldırılmıştır; önerilen alternatife bakın ]

Başka bir alternatif olarak, uygulamanızın yeniden başlatma gibi yönlendirme ve klavye görünürlüğü değişikliklerine neden olacak olayları dinlemesini ve bunları Etkinliğiniz içinde işlemesini sağlayabilirsiniz.

android:configChangesDüğümü, Etkinliğinizin manifest düğümüne ekleyerek başlayın

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

veya Android 3.2 (API seviye 13) ve daha yenisi için :

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

Daha sonra Etkinlik içinde onConfigurationChangedyöntemi geçersiz kılın ve setContentViewGUI mizanpajını yeni yönde yeniden yapılmaya zorlayın.

@Override
public void onConfigurationChanged(Configuration newConfig) {
  super.onConfigurationChanged(newConfig);
  setContentView(R.layout.myLayout);
}

17
İkinci yaklaşımın işe yaradığını düşünmüyorum. Denedim; EditText ile bir Etkinlik. Orada bir metin yazdım, yönünü değiştirdim ve metin gitti / sıfırlandı.
Ted

231
Gelecekte bir onRotate () yöntemi görmeyi umuyoruz. Böyle şeyler için endişelenmek bile - açıkçası - sinir bozucu.
Kelly Sutton

84
O Not Android Geliştirici Kılavuzu : Bu kullanılmasına karşı uyardı Not: (kullanma android:configChanges) kaçınılması ve sadece son çare olarak kullanılmalıdır. Bir yapılandırma değişikliğinden dolayı yeniden başlatmanın düzgün bir şekilde nasıl yönetileceği hakkında daha fazla bilgi için lütfen Çalışma Zamanı Değişikliklerini İşleme konusunu okuyun. Bunun yerine, rotasyon olayları boyunca veriyi devam ettirmek için onSaveInstanceState Bundle; veya @ Jon-O'nun bahsettiği gibi onRetainNonConfigurationInstance,.
Jeffro

19
Bu kötü bir çözümdür, çünkü yalnızca şu anda bilinen yapılandırma değişikliklerine tepki verir . Daha yeni Android sürümlerinde, bu kodun yakalanmayacağı diğer yapılandırma değişiklikleri oluşabilir (çünkü manifest'teki tüm yapılandırma değişikliklerini listelemesi gerekir). Durumun kaydedilmesinin çözümü, onRetainNonConfigurationChangeshataya karşı daha dayanıklı ve basittir.
Bananeweizen

16
Bu güncellemeyi 3.2'ye cevabınıza eklemeniz gerektiğini düşünüyorum , oldukça önemli (sadece bu problemle karşı karşıya kaldı) ve gözden kaçabilir.
bigstones

185

Android 3.2 ve sonraki sürümler için güncelleme:

Dikkat : Android 3.2'den (API seviye 13) başlayarak , cihaz dikey ve yatay yönlendirme arasında geçiş yaptığında "ekran boyutu" da değişir . Bu nedenle, API düzeyi 13 veya üstü için geliştirirken (minSdkVersion ve targetSdkVersion öznitelikleri tarafından bildirildiği gibi) yön değiştirme nedeniyle çalışma zamanı yeniden başlatmalarını önlemek istiyorsanız, "screenSize"değere ek olarak değeri de eklemeniz gerekir "orientation". Yani, beyan etmelisin android:configChanges="orientation|screenSize". Bununla birlikte, uygulamanız API seviye 12 veya daha düşük bir sürümü hedefliyorsa, etkinliğiniz her zaman bu yapılandırma değişikliğini kendisi yapar (bu yapılandırma değişikliği, bir Android 3.2 veya daha yüksek cihazda çalışırken bile etkinliğinizi yeniden başlatmaz).


1
Bu açıklama için teşekkürler, çünkü bu konuda bir yorum neredeyse beni içine bakmak için gönderdi. Şu anda API 8 hedefliyorum ve kodum configChanges üzerinde screenSize yok ve ICS çalıştıran cihazda (yeniden yönlendirme olmadan) iyi çalıştığını doğrulayabilir.
Carl

Bunu işaret ettiğiniz için teşekkürler, sadece android vardı: configChanges = "orientation | screenSize" seti ve oryantasyon geçişi Aktivitemi yeniden yaratıyordu ve benim hayatım için nedenini anlayamadım!
Christopher Perry

5
Android: configChanges eklenmesi yalnızca son çare olarak kullanılmalıdır . Bunun yerine Fragmentsve setRetainInstancekullanmayı düşünün .
Simon Forsberg

Kilit nokta screenSizeAndroid 3.2 ve üstü için sorunumu çözdü, teşekkürler!
fantouch

127

onCreate()Tamamen işten atılmayı durdurmaya çalışmak yerine Bundle savedInstanceState, olayın boş olup olmadığını görmek için olaya geçirileni kontrol etmeyi deneyebilirsiniz .

Örneğin Activity, her yönelim değişikliğinde değil, gerçekten oluşturulduğunda çalıştırılması gereken bir mantığım onCreate()varsa, bu mantığı yalnızca savedInstanceStatenull ise çalıştırırım .

Aksi takdirde, düzen için yine de düzgün bir şekilde yeniden çizilmesini istiyorum.

public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_game_list);

        if(savedInstanceState == null){
            setupCloudMessaging();
        }
}

bunun nihai cevap olup olmadığından emin değilim, ama benim için çalışıyor.


6
ve gerçekte nerede devlet tasarrufu yapıyorsunuz?
Ewoks

5
bu benim için çalışıyor gibi görünüyor ve açık ara en basit yöntem. Ben sadece bu konuda 4 ups var (benim dahil 5) vs 373 çok daha karmaşık görünüyor alt sınıf Uygulama hakkında fikir için. bu yöntemin bir dezavantajı var mı?
steveh

4
Bu çözüm benim için BÜYÜK çalıştı. i başardı Intent serverintent = new Intent(MainActivity.this, MessageListener.class);ve startService(serverintent);bir oluşturmak serverSocket = new ServerSocket(0xcff2);ve Socket client = serverSocket.accept();bir ile BufferedReader(new InputStreamReader(client.getInputStream()));ve benim android döndürmek ve aktif istemci / sunucu bağlantısını tutmak, henüz GUI döndürmek olabilir. El kitabına göre, son etkinlik kapatıldığında saveInstanceState başlatılır.
Fred F

3
Anlamıyorum, yakalama nedir? Bu harika çalışır ve diğer çözümlerden daha az karmaşıklığa sahiptir.
RTF

3
Android'de bunu yapmanın doğru yolu budur. Temel olarak configChanges ile bir dönüşü yakalamanın diğer yolları ve hantal, karmaşık ve gereksiz olanları.
LukeWaggoner

99

ben ne yaptım...

manifest'te etkinlik bölümüne şunu ekledi:

android:configChanges="keyboardHidden|orientation"

faaliyetin kodunda, uygulandı:

//used in onCreate() and onConfigurationChanged() to set up the UI elements
public void InitializeUI()
{
    //get views from ID's
    this.textViewHeaderMainMessage = (TextView) this.findViewById(R.id.TextViewHeaderMainMessage);

    //etc... hook up click listeners, whatever you need from the Views
}

//Called when the activity is first created.
@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    InitializeUI();
}

//this is called when the screen rotates.
// (onCreate is no longer called when screen rotates due to manifest, see: android:configChanges)
@Override
public void onConfigurationChanged(Configuration newConfig)
{
    super.onConfigurationChanged(newConfig);
    setContentView(R.layout.main);

    InitializeUI();
}

3
açıklığa kavuşturmak için: benim uygulama ile artık onCreate () ve onConfigurationChanged () değişken başlatma olabilir sadece ekran döndürme için çağrılacaktır. Değişkenleriniz artık ekran rotasyonlarından izole edilmiştir ;-) nice ve ez
Someone Somewhere Somewhere

2
Her şeyi burada açıklandığı gibi yaptım, ancak yön değiştirdikten sonra bir düğmeye basmaya çalıştığımda NullPointerException alıyorum. Ne yanlış olabilir?
Finnboy11

5
unutmayın cevabım 3 yaşında ve Android gelişmeye devam ediyor ... Simon - örnek kod için bir bağlantınız var mı? İnsanların ihtiyacı olan bu.
Bir Yerde Birisi

3
Android: configChanges'e karşı uyarı yaparken @ SimonAndréForsberg aslında sadece Android belgelerini yeniden yorumluyor . Çalışma Zamanı Değişikliklerini İşleme alternatifler hakkında daha ayrıntılı bilgi içerir (örnek kod dahil).
Leif Arne Storset

67

Açıkladığınız şey varsayılan davranıştır. Şunları ekleyerek bu olayları kendiniz tespit etmeniz ve yönetmeniz gerekir:

android:configChanges

manifestinize ve daha sonra ele almak istediğiniz değişikliklere. Yani yönlendirme için şunları kullanırsınız:

android:configChanges="orientation"

ve klavyenin açılıp kapanması için şunları kullanırsınız:

android:configChanges="keyboardHidden"

Her ikisini de ele almak istiyorsanız, bunları pipe komutuyla ayırabilirsiniz:

android:configChanges="keyboardHidden|orientation"

Bu, çağırdığınız herhangi bir Etkinlikte onConfigurationChanged yöntemini tetikler. Yöntemi geçersiz kılarsanız, yeni değerleri iletebilirsiniz.

Bu yardımcı olur umarım.


2
@GregD Biliyorum, bu yüzden bugünkü durumu yansıtacak şekilde güncellemek için iyi bir zaman. Bu sorunun sahip olduğu oyların sayısı göz önüne alındığında, hala SO hakkındaki diğer sorulardan bahsedilmektedir.
Simon Forsberg

48

Ben sadece bu irfanı keşfettim:

Etkinliği bir yönlendirme değişikliği yoluyla canlı tutmak ve üzerinde işlem yapmak için onConfigurationChanged, yukarıdaki belgeler ve kod örneği Manifest dosyasında bunu önerir:

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

ki bu her zaman işe yaradığı ekstra bir yararı vardır.

Bonus irfan ihmal olduğunu keyboardHiddenmantıklı görünebilir, ancak (en azından Android 2.1 için) emülatörü başarısızlıkları neden olur: Sadece belirterek orientationemülatörü çağrısı hem yapacak OnCreateve onConfigurationChangedbazen sadece OnCreatediğer zamanlar.

Bir cihazdaki hatayı görmedim, ancak emülatörün başkaları için başarısız olduğunu duydum. Bu yüzden belgelemeye değer.


14
Dikkat: Android 3.2'den (API seviye 13) başlayarak, cihaz dikey ve yatay yönlendirme arasında geçiş yaptığında "ekran boyutu" da değişir. Bu nedenle, API düzeyi 13 veya üstü için geliştirirken yön değiştirme nedeniyle çalışma zamanı yeniden başlatmalarını önlemek istiyorsanız: android: configChanges = "orientation | keyboardHidden | screenSize"
Geltrude

Evet, emülatör büyük zaman alıyor. Yapılandırma değişikliklerini doğru bir şekilde bildirmek için ona güvenemezsiniz.
IgorGanapolsky

Android: configChanges eklenmesi yalnızca son çare olarak kullanılmalıdır . Bunun yerine Fragmentsve setRetainInstancekullanmayı düşünün .
Simon Forsberg

38

Ayrıca, Android platformunun yön değişikliklerinde verilere devam etmenin yolunu kullanmayı da düşünebilirsiniz: onRetainNonConfigurationInstance()ve getLastNonConfigurationInstance().

Bu, bir sunucu getirmesinden elde ettiğiniz bilgiler veya hesaplanan onCreateveya bu tarihten beri başka bir şey gibi yapılandırma değişikliklerinde verileri korumanıza izin verirken, Android'in Activityxml dosyasını kullanımda olan yönlendirme için şimdi yeniden düzenlemesine izin verir. .

Buraya veya buraya bakın .

Bu yöntemlerin artık herkesin (yukarıda belirtilen çözümlerin çoğunun önerdiği gibi yön değiştirmekten daha esnek olmasına rağmen) kullanımdan kaldırıldığı Fragmentsve herkesin korumak istediğiniz setRetainInstance(true)her birine geçmesi ve bunun yerine kullanması önerisiyle belirtildiği unutulmamalıdır Fragment.


3
Ben gerçekten Fragments ve setRetainInstance bunu yapmak için en iyi yoldur (ve Google tarafından önerilen yolu), size +1 ve diğerlerine -1. Android ekleme: configChanges sadece son çare olarak kullanılmalıdır
Simon Forsberg

32

Bu yaklaşım yararlıdır, ancak Parçalar kullanılırken eksiktir.

Parçalar genellikle yapılandırma değişikliğinde yeniden oluşturulur. Bunun olmasını istemiyorsanız,

setRetainInstance(true); Parçanın yapıcılarında

Bu, yapılandırma değişikliği sırasında parçaların korunmasına neden olur.

http://developer.android.com/reference/android/app/Fragment.html#setRetainInstance(boolean)


7
Kabul. En yeni Android API'sı ile, Parçalar bununla başa çıkmanın doğru yolu gibi görünüyor. Henüz kendim denemedim, ancak bu sayfayı okurken topladığımdan , temelde bir Aktivitede uyguladığınız şeylerin% 99'unu bir Parçanın alt sınıfına taşıyın, sonra bu Parçayı Aktiviteye ekleyin. Etkinlik hala ekran döndürme üzerinde yok edilecek ve yeniden oluşturulacak, ancak özellikle Android'e @Abdo'nun bahsettiği yöntemi kullanarak Fragmanı yok etmemesini söyleyebilirsiniz setRetainInstance().
brianmearns


19

onCreateEğer değiştirdiğinizde yöntemi hala bile denir orientationandroid ait. Bu nedenle, tüm ağır işlevselliği bu yönteme taşımak size yardımcı olmayacaktır.


18

Aşağıdaki kodu <activity>etiketinizin içine yerleştirin Manifest.xml:

android:configChanges="screenLayout|screenSize|orientation"

17
 onConfigurationChanged is called when the screen rotates. 
 (onCreate is no longer called when screen rotates due to manifest, see:  
 android:configChanges)

Manifest'in hangi kısmı ona "deme" demiş onCreate()?

Ayrıca, Google'ın dokümanları kullanmaktan kaçındığını söyler android:configChanges(son çare hariç) .... Ancak daha sonra tüm DO kullanımlarını önerdikleri alternatif yöntemler android:configChanges.

Benim deneyimim öykünücü DAİMA onCreate()rotasyon üzerine çağırıyor .
Ama aynı kodu çalıştırdığım 1-2 cihaz ... çalışmıyor. (Neden herhangi bir fark olacağını bilmiyorum.)


16

Aşağıdaki adımları uygulamanız çok basit:

<activity
    android:name=".Test"
    android:configChanges="orientation|screenSize"
    android:screenOrientation="landscape" >
</activity>

Bu benim için çalışıyor:

Not: yönlendirme sizin requirment bağlıdır


15

Android bildiriminde yapılacak değişiklikler şunlardır:

android:configChanges="keyboardHidden|orientation" 

Faaliyet içinde yapılacak eklemeler şunlardır:

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

15

Manifestinize bu satırı ekleyin: -

android:configChanges="orientation|keyboard|keyboardHidden|screenSize|screenLayout|uiMode"

ve bu pasajı etkinliğe: -

@Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
    }

14

Bunu yapmanın birkaç yolu vardır:

Etkinlik Durumunu Kaydet

Etkinlik durumunu içine kaydedebilirsiniz onSaveInstanceState.

@Override
public void onSaveInstanceState(Bundle outState) {
    /*Save your data to be restored here
    Example : outState.putLong("time_state", time); , time is a long variable*/
    super.onSaveInstanceState(outState);
}

ve sonra bundledurumu geri yüklemek için kullanın .

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if(savedInstanceState!= null){
       /*When rotation occurs
        Example : time = savedInstanceState.getLong("time_state", 0); */
    } else {
      //When onCreate is called for the first time
    }
}

Oryantasyon değişikliklerini kendiniz halledin

Diğer bir alternatif ise yönelim değişikliklerini kendiniz halletmektir. Ancak bu iyi bir uygulama olarak kabul edilmez.

Bunu bildirim dosyanıza ekleyin.

android:configChanges="keyboardHidden|orientation"

Android 3.2 ve üstü için:

android:configChanges="keyboardHidden|orientation|screenSize"

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

if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
        //Handle rotation from landscape to portarit mode here
    } else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE){
        //Handle rotation from portrait to landscape mode here
    }
}

Döndürmeyi kısıtla

Ayrıca dönmeyi önlemek için etkinliğinizi dikey veya yatay modda sınırlayabilirsiniz.

Bunu bildirim dosyanızdaki etkinlik etiketine ekleyin:

        android:screenOrientation="portrait"

Veya bunu programınıza faaliyetinizde uygulayın:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}

11

Bunu yapmak için bulduk şekilde kullanmak bir onRestoreInstanceStateve onSaveInstanceStatekaydetmek için olaylar Bundle((herhangi bir değişken kaydedilmiş gerek yok bile, sadece orada Bundleboş olmayan bir şey koymak ). Ardından, onCreateyöntemde, Bundleboş olup olmadığını kontrol edin ve eğer öyleyse, başlatma işlemini yapın, değilse yapın.


11

"Android yolu" olmasa da, yönelim değişikliklerini kendim işleyerek ve değiştirilmiş yönlendirmeyi hesaba katmak için widget'ları basitçe yeniden konumlandırarak çok iyi sonuçlar aldım. Bu, diğer tüm yaklaşımlardan daha hızlıdır, çünkü görüşlerinizin kaydedilmesi ve geri yüklenmesi gerekmez. Aynı zamanda kullanıcıya daha sorunsuz bir deneyim sağlar, çünkü yeniden konumlandırılan widget'lar tam olarak aynı widget'tır, yeni taşınmış ve / veya yeniden boyutlandırılmıştır. Sadece model durumu değil, aynı zamanda görüş durumu da bu şekilde korunabilir.

RelativeLayoutzaman zaman kendini yeniden yönlendirmesi gereken bir görünüm için bazen iyi bir seçim olabilir. Her alt widget için bir dizi portre düzeni parametresi ve her birinde farklı göreceli konumlandırma kuralları olan bir dizi düzenlenmiş düzen parametresi sağlarsınız. Ardından, onConfigurationChanged()yönteminizde, uygun olanı setLayoutParams()her çocuktaki bir çağrıya geçirirsiniz . Herhangi bir çocuk denetiminin kendisinin dahili olarak yeniden yönlendirilmesi gerekiyorsa, yeniden yönlendirmeyi gerçekleştirmek için o çocuk üzerinde bir yöntem çağırmanız yeterlidir . O çocuk benzer herhangi yöntemlerini çağırır onun benzeri iç yeniden yönlendirilmesi gerekir ve çocuk kontrolleri.


Bunun bazı örnek kodlarını görmek isterim, parlak görünüyor!
Henrique de Sousa

8

Ekran her döndürüldüğünde, açılan etkinlik sona erer ve onCreate () yeniden çağrılır.

1. Ekran döndürüldüğünde etkinlik durumunu kaydetmek için bir şey yapabilirsiniz, böylece etkinliğin onCreate () öğesi tekrar çağrıldığında tüm eski şeyleri kurtarabilirsiniz. Bu bağlantıya bakın

2. Etkinliğin yeniden başlatılmasını önlemek istiyorsanız, aşağıdaki satırları manifest.xml dosyanıza yerleştirin.

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

7

parametresine tüm değeri depolamak için onSavedInstanceState yöntemini kullanmanız gerekir

@Override
    public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
        super.onSaveInstanceState(outState, outPersistentState);
        outPersistentState.putBoolean("key",value);
    }

ve kullan

@Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        savedInstanceState.getBoolean("key");
    } 

öğeyi görüntülemek ve değeri ekran döndürme işlemlerini gerçekleştirecek şekilde ayarlamak için


Bunun API seviyesi 22'ye ihtiyacı var.
Mohammad Afrashteh

6

Not: Gelecekte biri benimle aynı problemle karşılaşırsa bu yanıtı gönderirim. Benim için şu satır yeterli değildi:

android:configChanges="orientation"

Ekranı döndürdüğümde, `onConfigurationChanged (Yapılandırma newConfig) yöntemi çağrılmadı.

Çözüm: Sorun yönlendirmeyle ilgili olsa bile "screenSize" eklemek zorunda kaldım. AndroidManifest.xml dosyasında şunu ekleyin:

android:configChanges="keyboardHidden|orientation|screenSize"

Ardından yöntemi uygulayın onConfigurationChanged(Configuration newConfig)


5

Öğesinin etkinlik bölümüne şunu manifestekleyin:

android:configChanges="keyboardHidden|orientation"


4

İnsanlar kullanmanız gerektiğini söylüyor

android:configChanges="keyboardHidden|orientation"

Ancak Android'de döndürmeyi işlemenin en iyi ve en profesyonel yolu Loader sınıfını kullanmaktır. Ünlü bir sınıf değil (nedenini bilmiyorum), ama AsyncTask'tan çok daha iyi. Daha fazla bilgi için Udacity'nin Android kurslarında bulunan Android eğiticilerini okuyabilirsiniz.

Elbette, başka bir yol olarak, değerleri veya görünümleri onSaveInstanceState ile depolayabilir ve onRestoreInstanceState ile okuyabilirsiniz. Gerçekten size kalmış.


Evet, "profesyonel" görünmek için fazladan kodlar ekleyelim. Ya da sadece configurationChanges özniteliğiyle yapmanın hızlı, kolay, doğru ve denenmiş yoluna sadık kalmaya ne dersiniz?
AndroidDev

3

Bir süre deneme yanılma sonrasında, çoğu durumda ihtiyaçlarıma uygun bir çözüm buldum. Kod İşte:

Bildirim yapılandırması:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.pepperonas.myapplication">

    <application
        android:name=".App"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:configChanges="orientation|keyboardHidden|screenSize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>

</manifest>

Ana aktivite:

import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private static final String TAG = "MainActivity";

    private Fragment mFragment;

    private int mSelected = -1;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate  " + "");

        // null check not realy needed - but just in case...
        if (savedInstanceState == null) {

            initUi();

            // get an instance of FragmentTransaction from your Activity
            FragmentManager fragmentManager = getSupportFragmentManager();
            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

            /*IMPORTANT: Do the INITIAL(!) transaction only once!
            * If we call this everytime the layout changes orientation,
            * we will end with a messy, half-working UI.
            * */
            mFragment = FragmentOne.newInstance(mSelected = 0);
            fragmentTransaction.add(R.id.frame, mFragment);
            fragmentTransaction.commit();
        }
    }


    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        Log.d(TAG, "onConfigurationChanged  " +
                   (newConfig.orientation
                    == Configuration.ORIENTATION_LANDSCAPE
                    ? "landscape" : "portrait"));

        initUi();

        Log.i(TAG, "onConfigurationChanged - last selected: " + mSelected);
        makeFragmentTransaction(mSelected);
    }


    /**
     * Called from {@link #onCreate} and {@link #onConfigurationChanged}
     */
    private void initUi() {
        setContentView(R.layout.activity_main);
        Log.d(TAG, "onCreate  instanceState == null / reinitializing..." + "");
        Button btnFragmentOne = (Button) findViewById(R.id.btn_fragment_one);
        Button btnFragmentTwo = (Button) findViewById(R.id.btn_fragment_two);
        btnFragmentOne.setOnClickListener(this);
        btnFragmentTwo.setOnClickListener(this);
    }


    /**
     * Not invoked (just for testing)...
     */
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        Log.d(TAG, "onSaveInstanceState  " + "YOU WON'T SEE ME!!!");
    }


    /**
     * Not invoked (just for testing)...
     */
    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        Log.d(TAG, "onSaveInstanceState  " + "YOU WON'T SEE ME, AS WELL!!!");
    }


    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG, "onResume  " + "");
    }


    @Override
    protected void onPause() {
        super.onPause();
        Log.d(TAG, "onPause  " + "");
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy  " + "");
    }


    @Override
    public void onClick(View v) {

        switch (v.getId()) {
            case R.id.btn_fragment_one:
                Log.d(TAG, "onClick btn_fragment_one " + "");
                makeFragmentTransaction(0);
                break;

            case R.id.btn_fragment_two:
                Log.d(TAG, "onClick btn_fragment_two " + "");
                makeFragmentTransaction(1);
                break;

            default:
                Log.d(TAG, "onClick  null - wtf?!" + "");
        }
    }


    /**
     * We replace the current Fragment with the selected one.
     * Note: It's called from {@link #onConfigurationChanged} as well.
     */
    private void makeFragmentTransaction(int selection) {

        switch (selection) {
            case 0:
                mFragment = FragmentOne.newInstance(mSelected = 0);
                break;
            case 1:
                mFragment = FragmentTwo.newInstance(mSelected = 1);
                break;
        }

        // Create new transaction
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

        // Replace whatever is in the fragment_container view with this fragment,
        // and add the transaction to the back stack
        transaction.replace(R.id.frame, mFragment);

        /*This would add the Fragment to the backstack...
        * But right now we comment it out.*/
        //        transaction.addToBackStack(null);

        // Commit the transaction
        transaction.commit();
    }

}

Ve örnek Parçası:

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * @author Martin Pfeffer (pepperonas)
 */
public class FragmentOne extends Fragment {

    private static final String TAG = "FragmentOne";


    public static Fragment newInstance(int i) {
        Fragment fragment = new FragmentOne();
        Bundle args = new Bundle();
        args.putInt("the_id", i);
        fragment.setArguments(args);
        return fragment;
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        Log.d(TAG, "onCreateView  " + "");
        return inflater.inflate(R.layout.fragment_one, container, false);
    }

}

Github'da bulunabilir .


3

orientationFarklı yönlerde farklı görevleri gerçekleştirmek için dinleyiciyi kullanın .

@Override
public void onConfigurationChanged(Configuration myConfig) 
{
    super.onConfigurationChanged(myConfig);
    int orient = getResources().getConfiguration().orientation; 
    switch(orient) 
    {
       case Configuration.ORIENTATION_LANDSCAPE:
          setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                    break;
       case Configuration.ORIENTATION_PORTRAIT:
          setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                    break;
       default:
          setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
    }
}

3

Senin içinde kodunun altına koy Activityin Android Manifest.

android:configChanges="orientation"

Bu, yönlendirmeyi değiştirdiğinizde etkinliğinizi yeniden başlatmaz.


2
@Mavamaarten Muhtemelen başkalarının işaret ettiği gibi, kötü bir uygulama ve diğer 10 cevap zaten bunu kapsıyor.
MikkoP

3

Ekran yönünü (yatay veya dikey) sabitleyin AndroidManifest.xml

android:screenOrientation="portrait" veya android:screenOrientation="landscape"

bunun için onResume()yönteminiz çağrılmaz.


5
nasıl bir şey tamir cehennem bir cevap? Cihazları kullanarak kullanıcıları kilitlersek neden cihazlarımız dönebilir?
56'da Reinherd

3

Google tarafından sunulan android architechure en iyi bileşenlerinden biri ViewModel olan tüm gereksinimi yerine getirecektir.

Kullanıcı arabirimi ile ilgili verileri yaşam döngüsü şeklinde depolamak ve yönetmek için tasarlanmıştır, ayrıca ekran döndükçe verilerin hayatta kalmasını sağlar

class MyViewModel : ViewModel() {

Lütfen buna bakın: https://developer.android.com/topic/libraries/architecture/viewmodel


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.