Як виявити зміну орієнтації в макеті в Android?


110

Я щойно застосував функцію зміни орієнтації - наприклад, коли макет змінюється від портретного до пейзажного (або навпаки). Як я можу виявити, коли подія зміни орієнтації закінчилося.

Не OrientationEventListenerвийшло. Як я можу отримувати сповіщення про події зміни орієнтації макета?


У моєму випадку onCreate () викликався при зміні орієнтації.
Джозель Новес

Відповіді:


293

Використовуйте метод активності onConfigurationChanged . Дивіться наступний код:

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

Ви також повинні відредагувати відповідне елемент у вашому файлі маніфесту, щоб включити android: configChanges Просто дивіться код нижче:

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

ПРИМІТКА. За допомогою Android 3.2 (рівень API 13) або вище, "розмір екрана" також змінюється, коли пристрій перемикається між портретною та пейзажною орієнтацією. Таким чином, якщо ви хочете запобігти перезапуску часу виконання через зміни орієнтації при розробці для API рівня 13 або вище, ви повинні оголосити android: configChanges = "орієнтація | screenSize" для API рівня 13 або вище .

Сподіваюся, це допоможе тобі ... :)


3
Це добре, але він завантажує макет xml у папку layout-land, він використовує портретні файли макета xml.
Програміст

22
Aztec Coder, коли ви включаєте "android: configChanges =" орієнтація ", ви заявляєте, що будете керувати зміною орієнтації, а це означає, що ваша активність не буде відтворена при переході на ландшафт. Натомість називається onConfigurationChanged. Якщо це небажано , ви можете використовувати змінну, щоб запам’ятати орієнтацію вашої діяльності і кожен раз, коли ви переходите на Паузу (наприклад), щоб перевірити, чи орієнтація все-таки однакова.
Олена,

14
Якщо ви розробляєте для API рівня 13 (3.2) або вище, вам слід вказати android: configChanges = "орієнтація | screenSize", інакше onConfigurationChanged не буде називатися: developer.android.com/guide/topics/resources/…
Arne

1
Привіт, я будую свій додаток з API 10 (Android 2.3.3). І він прекрасно розпізнає орієнтацію, коли я використовую android: configChanges = "орієнтація | клавіатураHidden". Але мій Nexus S, який працює на Android 4.1.2, не визначає зміни орієнтації. Що мені робити?
Картік Андгаміл

2
використовуйте android: configChanges = "орієнтація | screenSize" замість android: configChanges = "орієнтація | клавіатураHidden" у вашому файлі маніфесту та перевірте ... !!!
Дінеш Шарма

15

Для завантаження макета в макеті-земельні засобах папки у вас є два окремих макети , то ви повинні зробити setContentViewв onConfigurationChangedметоді.

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

Якщо у вас є тільки один макет, тоді немає необхідності вводити setContentView у цьому методі. просто

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

19
Замість перевизначення просто використовуйте layout / main.xml та layout-land / main.xml.
Джаред Берроуз

@JaredBurrows: Будь ласка , см stackoverflow.com/questions/23789605 / ...
B. Clay Shannon

Я хотів виявити, що моя діяльність була припинена через обертання екрана. Я реалізував onConfigurationChanged(Configuration newConfig)метод (як у цій відповіді), але замість того, щоб сам ним керувати, встановив булевий прапор, а потім назвав recreate()метод, щоб Android відтворив активність у звичайному режимі.
запаморочив

Одна з проблем recreate()методу полягає в тому, що він змушує екран коротко блимати чорним кольором. З цієї причини я застосував інший підхід: (1) зберегти ширину екрана в onCreate(...)(2) порівняти збережену ширину екрана з поточною шириною екрана в будь-якому методі життєвого циклу, коли діяльність припиняється (наприклад onSaveInstanceState(...)).
запаморочив

13

Просто хотів показати вам спосіб зберегти весь пакет після onConfigurationChanged:

Створіть новий пакет відразу після уроку:

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

Далі, після "захищеної недійсності onCreate" додайте це:

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

Якщо ви додасте це, всі ваші класифіковані класи в MainActivity будуть збережені.

Але найкращий спосіб - додати це у свій AndroidManifest:

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

7
Це вводить в оману. Реалізація onConfigurationChanged()робить це таким чином, що ваш instanceState не знищується при зміні орієнтації, тому вам не доведеться зберігати його. Ви можете зберегти його для інших подій у життєвому циклі діяльності, але я не знаю.
izzy

5

використовувати цей метод

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

І не забудьте додати це у свій Androidmainfest.xml

android:configChanges="orientation|screenSize"

подобається це

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

    </activity>

2

Метод заміщення активності onConfigurationChanged


Я хотів би зазначити, що без наступного рядка всередині тега <activity> в маніфесті, зворотний виклик onConfigurationChanged () не був би навіть запущений. android: configChanges = "орієнтація"
Sreekanth Karumanaghat

1

Я просто хочу запропонувати ще одну альтернативу, яка стосуватиметься деяких із вас, як це було пояснено вище:

android:configChanges="orientation|keyboardHidden" 

Має на увазі, що ми явно оголошуємо макет для введення.

У випадку, якщо ми хочемо зберегти автоматичну ін’єкцію завдяки папці макет-земля та макет. Все, що вам потрібно зробити - це додати його до onCreate:

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

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

Тут ми відображаємо чи не панель дій залежно від орієнтації телефону


0

Створіть екземпляр OrientationEventListenerкласу та ввімкніть його.

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

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

2
Будь ласка, не скасовуйте свою відповідь. Якщо ви хочете видалити її, ви можете знайти кнопку видалення внизу зліва від вашої відповіді.
CalvT

0

Якщо прийнята відповідь не працює для вас, переконайтеся, що ви не визначились у файлі маніфесту:

android:screenOrientation="portrait"

Який мій випадок.


0

У випадку, якщо це корисно для деяких нових розробників, оскільки його не вказано вище. Просто, щоб бути дуже явним:

Якщо ви використовуєте onConfigurationChanged, вам потрібно дві речі :

  1. onConfigurationChangedМетод у вашій діяльності класу

  2. Вкажіть у своєму маніфесті, які зміни конфігурації будуть оброблятися вашим onConfigurationChangedметодом

Фрагмент маніфесту в наведених вище відповідях, хоча, без сумніву, правильний для конкретного додатка, до якого належить маніфест, НЕ є саме тим, що потрібно додати до маніфесту, щоб запустити метод onConfigurationChanged у вашому класі активності. тобто наведений нижче маніфест може бути невірним для вашої програми.

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

У наведеному вище маніфестному документі є різні дії Android, android:configChanges=""які можуть викликати onCreate у життєвому циклі діяльності.

Це дуже важливо - ті, які НЕ вказані в маніфесті, - це ті, які запускають onCreate, і ті, які вказані в маніфесті, - це ті, які запускають ваш onConfigurationChangedметод у вашому класі активності.

Отже, вам потрібно визначити, які зміни конфігурації потрібно обробити самостійно. Для Android Encyclopedically Chellenged, як я, я використав швидкі підказки спливаючих вікон в Android Studio і додав майже в усі можливі варіанти конфігурації. Перерахувавши все це в основному говорив, що я б обробляти все, і onCreate ніколи не буде викликаний через конфігурації.

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

Зараз явно я не хочу впоратись із усім, тому я почав виключати описані вище варіанти один за одним. Повторне створення та тестування мого додатка після кожного видалення.

Ще один важливий момент : Якщо лише один параметр конфігурації обробляється автоматично, що запускає onCreate (у вас немає його, зазначеного у вашому маніфесті вище), то, схоже, onConfigurationChangedвін не працює. Ви повинні внести всі відповідні у свій маніфест.

Я закінчив 3, які спрацьовували onCreate спочатку, потім я протестував на S10 +, і я все ще отримував onCreate, тому мені довелося робити мою вправу усунення ще раз, і мені також потрібні були |screenSize. Тож тестуйте на підборі платформ.

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

Тож моя пропозиція, хоча я впевнений, що хтось може прорізати дірки в цьому:

  1. Додайте свій onConfigurationChangedметод у свій клас активності за допомогою TOAST або LOG, щоб ви могли побачити, коли він працює.

  2. Додайте до маніфесту всі можливі параметри конфігурації.

  3. Перевірте, onConfigurationChangedчи працює ваш метод, перевіривши додаток.

  4. Видаліть кожен параметр конфігурації з файлу маніфесту по одному, тестуючи додаток після кожного.

  5. Тестуйте на якомога більшій кількості пристроїв.

  6. Не копіюйте та не вставляйте мій фрагмент вище у файл маніфесту. Оновлення Android змінюють список, тому використовуйте підказки Android Studio, щоб переконатися, що ви все отримали.

Я сподіваюся, що це економить когось деякий час.

Мій onConfigurationChangedметод лише для інформації нижче. onConfigurationChangedвикликається в життєвому циклі після появи нової орієнтації, але до того, як інтерфейс користувача був відтворений. Отже, моя перша ifперевірка орієнтації працює правильно, а потім 2-я вкладена, ifщоб переглянути видимість мого інтерфейсу ImageView, також працює правильно.

    @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

для реалізації Kotilin у найпростішій формі - спрацьовує лише тоді, коли екран змінюється з портретного <--> ландшафту, якщо потрібен пристрій виявлення відкидання (180 градусів), вам потрібно буде вкласти значення датчика тяжкості

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


    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.