Как определить изменение ориентации макета в Android?

110

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

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

user403015
источник
В моем случае onCreate () вызывался при изменении ориентации.
Josiel Novaes

Ответы:

293

Используйте метод Activity 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 = "direction | screenSize" для уровня API 13 или выше .

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

Динеш Шарма
источник
3
Это хорошо, но он загружает макет xml в папку layout-land, он использует файлы макета портретного xml.
Программист
23
Aztec Coder, когда вы включаете "android: configChanges =" Ориентация ", вы заявляете, что обработаете изменение ориентации, что означает, что ваша деятельность не будет воссоздана при переключении в альбомную ориентацию. Вместо этого вызывается onConfigurationChanged. Если это нежелательно , вы можете использовать переменную, чтобы запоминать ориентацию вашей деятельности, и каждый раз, когда вы заходите в onPause (например), чтобы проверять, остается ли ориентация прежней.
Елена
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 = "Ориентация | keyboardHidden". Но мой Nexus S под управлением Android 4.1.2 не обнаруживает изменения ориентации, что мне делать?
Картик Андхамил
2
используйте android: configChanges = "Ориентация | screenSize" вместо android: configChanges = "Ориентация | keyboardHidden" в вашем файле манифеста и проверьте ... !!!
Динеш Шарма
15

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

Просто хотел показать вам способ сохранить весь ваш 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"/>
Николай Христов
источник
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 = "Ориентация"
Шрикант Каруманагат
1

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

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

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

Z3nk
источник
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 в жизненном цикле Activity.

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

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

        }
    }
DMur
источник
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")


    }
}
альфа911
источник