Как обнаружить изменение ориентации в макете в Android?

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

OrientationEventListener не работал Как получить уведомления о событиях изменения ориентации макета?

11 ответов

Решение

Используйте метод onConfigurationChanged для Activity. Смотрите следующий код:

@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="direction|screenSize" для уровня API 13 или выше.

Надеюсь, что это поможет вам...:)

Загрузка макета в папку layout-land означает, что у вас есть два отдельных макета, тогда вам нужно сделать 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);
}

Просто хотел показать вам способ сохранить все ваши Bundle после onConfigurationChanged:

Создайте новый Bundle сразу после вашего класса:

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

Далее, после "protected void 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"/>

Использовать этот метод

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

В случае, если это полезно для некоторых новых разработчиков, потому что это не указано выше. Чтобы быть очень точным:

При использовании onConfigurationChanged вам понадобятся две вещи:

  1. An onConfigurationChanged метод в вашем классе активности

  2. Укажите в манифесте, какие изменения конфигурации будут обрабатываться вашимonConfigurationChanged метод

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

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

В приведенной выше записи манифеста есть различные действия Android для android:configChanges="" который может вызвать onCreate в жизненном цикле вашей деятельности.

Это очень важно - те, которые НЕ указаны в манифесте, это те, которые запускают ваш onCreate, а те, которые указаны в манифесте, это те, которые запускают вашonConfigurationChangedметод в вашей деятельности класса.

Итак, вам нужно определить, какие изменения конфигурации вам нужно обработать самостоятельно. Для Android Encyclopedically Challenged, как я, я использовал всплывающие подсказки в 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);
            }

        }
    }

Переопределить метод действия onConfigurationChanged

Я просто хочу предложить другую альтернативу, которая действительно затронет некоторых из вас, как описано выше:

android:configChanges="orientation|keyboardHidden" 

подразумевает, что мы явно объявляем макет для внедрения.

В случае, если мы хотим сохранить автоматический впрыск благодаря папкам layout-land и layout. Все, что вам нужно сделать, это добавить его в onCreate:

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

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

Здесь мы отображаем или нет панель действий в зависимости от ориентации телефона

Создать экземпляр OrientationEventListener учебный класс

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

Если кто-то еще слишком долго занимается этим, как я, на эмуляторе это не работает. Должно быть настоящее устройство.

Для реализации 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")


    }
}

Если принятый ответ не работает для вас, убедитесь, что вы не определили в файле манифеста:

android:screenOrientation="portrait"

Какой мой случай.

Другие вопросы по тегам