Bagaimana cara mendeteksi perubahan orientasi dalam tata letak di Android?

110

Saya baru saja menerapkan fitur perubahan orientasi - misalnya saat tata letak berubah dari potret ke lanskap (atau sebaliknya). Bagaimana saya bisa mendeteksi ketika acara perubahan orientasi selesai.

Itu OrientationEventListenertidak berhasil. Bagaimana saya bisa mendapatkan pemberitahuan tentang peristiwa perubahan orientasi tata letak?

pengguna403015
sumber
Dalam kasus saya, onCreate () dipanggil ketika orientasi berubah.
Josiel Novaes

Jawaban:

293

Gunakan metode onConfigurationChanged dari Aktivitas. Lihat kode berikut:

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

Anda juga harus mengedit yang sesuai elemen dalam file manifes Anda untuk menyertakan android: configChanges Lihat saja kode di bawah ini:

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

CATATAN: dengan Android 3.2 (API level 13) atau yang lebih tinggi, "ukuran layar" juga berubah saat perangkat beralih antara orientasi potret dan lanskap. Jadi, jika Anda ingin mencegah waktu proses dimulai ulang karena perubahan orientasi saat mengembangkan API level 13 atau lebih tinggi, Anda harus mendeklarasikan android: configChanges = "orientasi | screenSize" untuk API level 13 atau lebih tinggi .

Semoga ini bisa membantu Anda ... :)

Dinesh Sharma
sumber
3
Ini bagus, tetapi ini tidak memuat layout xml di folder layout-land, ia menggunakan file layout potret xml.
Programmer
22
Aztec Coder, saat Anda menyertakan "android: configChanges =" orientasi "Anda menyatakan bahwa Anda akan menangani perubahan orientasi yang berarti bahwa aktivitas Anda tidak akan dibuat ulang saat Anda beralih ke lanskap. Sebagai gantinya, onConfigurationChanged dipanggil. Jika ini tidak diinginkan , Anda dapat menggunakan variabel untuk mengingat orientasi aktivitas Anda dan setiap kali Anda melalui onPause (misalnya) untuk memeriksa apakah orientasinya masih sama.
Elena
14
Jika Anda mengembangkan untuk API level 13 (3.2) atau lebih tinggi, Anda harus menentukan android: configChanges = "orientasi | screenSize", jika tidak onConfigurationChanged tidak akan dipanggil: developer.android.com/guide/topics/resources/…
Arne
1
Hai, Saya sedang membangun aplikasi saya dengan API 10 (Android 2.3.3). Dan itu mengenali orientasi dengan sempurna ketika saya menggunakan android: configChanges = "orientasi | keyboardHidden". Tetapi Nexus S saya yang menjalankan Android 4.1.2 tidak mendeteksi perubahan orientasi. Apa yang harus saya lakukan?
Karthik Andhamil
2
gunakan android: configChanges = "orientasi | screenSize" alih-alih android: configChanges = "orientasi | keyboardHidden" di file manifes Anda dan periksa ... !!!
Dinesh Sharma
15

Untuk memuat layout di folder layout-land berarti anda memiliki dua layout terpisah maka harus anda buatsetContentView di onConfigurationChangedmetode.

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

Jika Anda hanya memiliki satu layout maka tidak perlu membuat setContentView dalam metode ini. secara sederhana

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
}
Veerababu Medisetti
sumber
19
Daripada menimpa, cukup gunakan layout / main.xml dan layout-land / main.xml.
Jared Burrows
@JaredBurrows: Silakan lihat stackoverflow.com/questions/23789605/…
B. Clay Shannon
Saya ingin mendeteksi bahwa aktivitas saya dihentikan karena rotasi layar. Saya mengimplementasikan onConfigurationChanged(Configuration newConfig)metode (seperti dalam jawaban ini), tetapi alih-alih menanganinya sendiri, saya menetapkan flag Boolean dan kemudian memanggil recreate()metode tersebut sehingga Android membuat ulang aktivitas dengan cara normal.
linglung
Satu masalah dengan recreate()metode ini adalah ini menyebabkan layar berkedip hitam sebentar. Untuk alasan ini saya menggunakan pendekatan lain: (1) simpan lebar layar di onCreate(...), (2) bandingkan lebar layar yang disimpan dengan lebar layar saat ini dalam metode siklus-hidup saat aktivitas dihentikan (misalnya onSaveInstanceState(...)).
bingung
13

Hanya ingin menunjukkan cara menyimpan semua Bundel Anda setelah onConfigurationChanged:

Buat Bundel baru tepat setelah kelas Anda:

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

Selanjutnya, setelah "protected void onCreate" tambahkan ini:

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

Jika Anda menambahkan ini, semua kelas Anda yang terkurung ke dalam MainActivity akan disimpan.

Tetapi cara terbaik adalah dengan menambahkan ini di AndroidManifest Anda:

<activity name= ".MainActivity" android:configChanges="orientation|screenSize"/>
Nikolay Hristov
sumber
7
Ini menyesatkan. Menerapkan onConfigurationChanged()membuatnya jadi instanceState Anda tidak dihancurkan saat orientasi berubah, jadi Anda tidak perlu menyimpannya. Anda mungkin ingin menyimpannya untuk acara lain dalam daur hidup aktivitas, tapi saya tidak tahu.
izzy
5

gunakan metode ini

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

Dan jangan lupa untuk menambahkan ini di Androidmainfest.xml Anda

android:configChanges="orientation|screenSize"

seperti ini

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

    </activity>
Sai Gopi Me
sumber
2

Ganti metode aktivitas onConfigurationChanged

Flavio
sumber
Saya ingin menunjukkan bahwa tanpa baris berikut di dalam tag <activity> dalam manifes, panggilan balik onConfigurationChanged () bahkan tidak akan dipicu. android: configChanges = "orientasi"
Sreekanth Karumanaghat
1

Saya hanya ingin mengusulkan alternatif lain yang akan menjadi perhatian sebagian dari Anda, seperti yang dijelaskan di atas:

android:configChanges="orientation|keyboardHidden" 

menyiratkan bahwa kami secara eksplisit mendeklarasikan tata letak yang akan diinjeksi.

Jika kami ingin mempertahankan injeksi otomatis berkat folder tata letak-tanah dan tata letak. Yang harus Anda lakukan adalah menambahkannya ke onCreate:

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

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

Di sini, kami menampilkan atau tidak bilah tindakan tergantung pada orientasi ponsel

Z3nk
sumber
0

Buat instance OrientationEventListenerkelas dan aktifkan.

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

if (mOrientationEventListener.canDetectOrientation())
    mOrientationEventListener.enable();
James Fenn
sumber
2
Tolong jangan merusak jawaban Anda. Jika Anda ingin menghapusnya, Anda dapat menemukan tombol hapus di kiri bawah jawaban Anda.
CalvT
0

Jika jawaban yang diterima tidak berhasil untuk Anda, pastikan Anda tidak menentukan dalam file manifes:

android:screenOrientation="portrait"

Yang mana kasus saya.

Jiyeh
sumber
0

Dalam hal ini digunakan untuk beberapa pengembang yang lebih baru karena tidak ditentukan di atas. Hanya untuk menjadi sangat eksplisit:

Anda memerlukan dua hal jika menggunakan onConfigurationChanged :

  1. Sebuah onConfigurationChangedmetode dalam Anda Kelas Aktivitas

  2. Tentukan dalam manifes Anda perubahan konfigurasi mana yang akan ditangani olehonConfigurationChanged metode Anda

Cuplikan manifes dalam jawaban di atas, meskipun tidak diragukan lagi benar untuk aplikasi tertentu yang memiliki manifes, BUKAN persis seperti yang perlu Anda tambahkan dalam manifes untuk memicu metode onConfigurationChanged di Kelas Aktivitas Anda. yaitu entri manifes di bawah ini mungkin tidak benar untuk aplikasi Anda.

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

Dalam entri manifes di atas, ada berbagai tindakan Android android:configChanges=""yang bisa memicu onCreate dalam siklus hidup Aktivitas Anda.

Ini sangat penting - Yang TIDAK Ditentukan dalam manifes adalah yang memicu onCreate Anda dan Yang ditentukan dalam manifes adalah yang memicu onConfigurationChangedmetode Anda Anda di Kelas Aktivitas.

Jadi, Anda perlu mengidentifikasi perubahan konfigurasi mana yang perlu Anda tangani sendiri. Untuk Android Encyclopedically Challenged seperti saya, saya menggunakan pop-out petunjuk cepat di Android Studio dan menambahkan di hampir setiap opsi konfigurasi yang memungkinkan. Mendaftar semua ini pada dasarnya mengatakan bahwa saya akan menangani semuanya dan onCreate tidak akan pernah dipanggil karena konfigurasi.

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

Sekarang jelas saya tidak ingin menangani semuanya, jadi saya mulai menghilangkan opsi di atas satu per satu. Membangun kembali dan menguji aplikasi saya setelah setiap penghapusan.

Poin penting lainnya : Jika hanya ada satu opsi konfigurasi yang ditangani secara otomatis yang memicu onCreate Anda (Anda tidak memilikinya tercantum dalam manifes Anda di atas), maka akan muncul sepertionConfigurationChanged tidak berfungsi. Anda harus memasukkan semua yang relevan ke dalam manifes Anda.

Saya berakhir dengan 3 yang awalnya memicu onCreate, kemudian saya menguji S10 + dan saya masih mendapatkan onCreate, jadi saya harus melakukan latihan eliminasi lagi dan saya juga membutuhkan |screenSize. Jadi uji pada beberapa platform.

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

Jadi saran saya, meskipun saya yakin seseorang bisa membuat lubang di sini:

  1. Tambahkan onConfigurationChangedmetode Anda di Kelas Aktivitas dengan TOAST atau LOG ​​sehingga Anda dapat melihat kapan metode tersebut berfungsi.

  2. Tambahkan semua opsi konfigurasi yang memungkinkan ke manifes Anda.

  3. Konfirmasikan bahwa onConfigurationChangedmetode Anda berfungsi dengan menguji aplikasi Anda.

  4. Hapus setiap opsi konfigurasi dari file manifes Anda satu per satu, uji aplikasi Anda setelahnya.

  5. Uji pada sebanyak mungkin variasi perangkat.

  6. Jangan salin / tempel cuplikan saya di atas ke file manifes Anda. Pembaruan Android mengubah daftar, jadi gunakan petunjuk Android Studio yang muncul untuk memastikan Anda mendapatkan semuanya.

Saya harap ini menghemat waktu seseorang.

onConfigurationChangedCara saya hanya untuk info dibawah ini. onConfigurationChangeddipanggil dalam siklus proses setelah orientasi baru tersedia, tetapi sebelum UI dibuat ulang. Oleh karena itu pertama saya ifuntuk memeriksa orientasi berfungsi dengan benar, dan kemudian bersarang ifke -2 untuk melihat visibilitas UI ImageView saya juga berfungsi dengan benar.

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

        }
    }
DMur
sumber
0

untuk implementasi Kotilin dalam bentuk yang paling sederhana - hanya aktif saat layar berubah dari potret <--> lanskap jika perangkat memerlukan deteksi balik (180 derajat), Anda harus memasukkan nilai sensor gravitasi

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


    }
}
alpha911
sumber