Как отключить изменение ориентации на Android?


287

У меня есть приложение, которое я просто хотел бы использовать в портретном режиме, поэтому я определил android: screenOrientation = "Portrait" в манифесте XML. Это работает нормально для телефона HTC Magic (и предотвращает изменение ориентации на других телефонах).

Но у меня проблема с телефоном HTC G1, когда я открываю аппаратную QWERTY-клавиатуру (не виртуальную клавиатуру). Моя активность остается в портретном режиме, но, похоже, она перезапускается и теряет все свои состояния. Этого не происходит с версией HTC Hero .

Мое приложение довольно большое, поэтому я не хочу, чтобы оно перезапускалось и теряло все свои состояния при открытой клавиатуре. Как я могу предотвратить это?


2
Попробуйте поискать здесь: stackoverflow.com/questions/2366706/…
Энди Вайнштейн

Ответы:


317

Обновление апрель 2013: не делай этого. Это не было хорошей идеей в 2009 году, когда я впервые ответил на вопрос, и сейчас это действительно не очень хорошая идея. Посмотрите этот ответ hackbod по причинам:

Избегайте перезагрузки активности с асинхронной задачей при изменении ориентации в Android

Добавьте android:configChanges="keyboardHidden|orientation"в свой AndroidManifest.xml. Это говорит системе, с какими изменениями конфигурации вы собираетесь справиться самостоятельно - в этом случае ничего не делать.

<activity android:name="MainActivity"
     android:screenOrientation="portrait"
     android:configChanges="keyboardHidden|orientation">

См. Ссылку для разработчиков configChanges для более подробной информации.

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

Обновление: Начиная с Android 3.2, вам также необходимо добавить «screenSize»:

<activity
    android:name="MainActivity"
    android:screenOrientation="portrait"
    android:configChanges="keyboardHidden|orientation|screenSize">

Из руководства разработчика. Обработка конфигурации.

Внимание! Начиная с Android 3.2 (уровень API 13), «размер экрана» также изменяется, когда устройство переключается между книжной и альбомной ориентацией. Таким образом, если вы хотите предотвратить перезапуск среды выполнения из-за изменения ориентации при разработке для API уровня 13 или выше (как объявлено атрибутами minSdkVersion и targetSdkVersion), вы должны включить значение «screenSize» в дополнение к значению «direction». То есть ты должен объявить android:configChanges="orientation|screenSize". Однако, если ваше приложение предназначено для уровня API 12 или ниже, то ваша активность всегда сама обрабатывает это изменение конфигурации (это изменение конфигурации не перезапускает вашу активность, даже при работе на устройстве Android 3.2 или выше).


36
Просто чтобы добавить к этому и быть действительно явным, Android может безжалостно убить ваше приложение в любое время, независимо от изменений ориентации, поэтому вы должны использовать onPause () и onSaveInstanceState () для сохранения состояния, несмотря ни на что.
Эрик Милл

Обновление 3.2 было очень полезным и блокировало меня. Я понятия не имел, почему мой обработчик onConfigurationChanged не сработал, и это все. Спасибо!
sweetlilmre

третий параметр - screenSize не может быть найден в 2.3.x, я должен измениться на screenLayout?
Deadfish

2
@Lumma Нет, «screenSize» необходим только для Android 3.2 и новее. На какой уровень API вы ориентируетесь? Я думаю, что вам нужно только добавить его, если вы нацелены на уровень 13 или выше. Я уточню ответ, чтобы уточнить.
Интриги

1
На всякий случай, если это полезно для других людей, я нашел вас обоих <... android: configChanges = "Ориентация" ...> для отмены изменений и <... android: screenOrientation = "Portrait" ...> для определить по умолчанию.
Sogger

97

Вам нужно изменить AndroidManifest.xml, как упоминалось в Intrications (ранее Ashton), и убедиться, что действие обрабатывает событие onConfigurationChanged так, как вы хотите, чтобы оно обрабатывалось. Вот как это должно выглядеть:

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

Как отметил Дмитрий Зайцев, то лучше поставить setRequestedOrientation()в систему onCreate().
Тимммм

3
Не вызывается onConfigurationChanged()раньше, onCreate()если так лучше установить ориентацию перед настройкой contentViews в oncreate , настройка конфигурации, к которой он принадлежит, также более чистая, поэтому этот ответ все еще остается хорошим.
Самуил

39

Я всегда находил, что вам нужны оба

android:screenOrientation="nosensor" android:configChanges="keyboardHidden|orientation"

22

Как сказано, установите android:configChangesвашу активность (в файле манифеста), keyboardHidden|orientationа затем:

1) Переопределить onConfigurationChanged()

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    //here you can handle orientation change
}

2) Добавьте эту строку к вашей деятельности onCreate()

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

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

Также вы можете установить android:screenOrientation="nosensor"для вашей деятельности (в манифесте). Но, используя этот способ, вы вообще не сможете справиться с изменениями ориентации.


Что мне делать, если я хочу избежать повторного создания действия при ротации, но я хочу разрешить пользователю блокировать ориентацию через настройки ОС?
Android-разработчик

@androiddeveloper, это отдельный вопрос, на который уже есть ответ: stackoverflow.com/a/14771495/926907
Дмитрий Зайцев

Ваша ссылка касается изменения содержимого самостоятельно при изменении конфигурации, но я хотел бы избежать ротации действия (чтобы оно оставалось в точности таким, как оно выглядит) в случае, если пользователь решил заблокировать ориентацию через ОС настройки (доступно на некоторых устройствах через быстрые настройки, в ящике уведомлений).
Android-разработчик

@ androiddeveloper ах, думаю, я понял. Затем взгляните на эту ссылку: developer.android.com/reference/android/… Согласно документам, ориентация по умолчанию уже должна учитывать предпочтения пользователя. Если это не так, то я подозреваю, что это специфическое поведение ОС. Буду рад услышать о ваших результатах - теперь мне это тоже интересно :)
Дмитрий Зайцев

Я знаю, что по умолчанию будет обрабатываться предпочтения пользователя, но он также воссоздает действие при повороте экрана, чего я не хочу иметь.
Android-разработчик


13

В методе OnCreate вашей активности используйте этот код:

    @Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

Теперь ваша ориентация будет установлена ​​на портрет и никогда не изменится.


4
При этом вы не препятствуете повторному запуску действия каждый раз, когда изменяется конфигурация ориентации.
AxeEffect

Кроме того, это не будет работать, если вы введете действие из предыдущего действия в альбомной ориентации.
w3bshark

10

В файле AndroidManifest.xml для каждого действия, которое вы хотите заблокировать, добавьте последнюю screenOrientationстроку:

android:label="@string/app_name"
android:name=".Login"
android:screenOrientation="portrait" >

Или андроид: screenOrientation = "пейзаж" .


8

В вашем файле androidmanifest.xml :

   <activity android:name="MainActivity" android:configChanges="keyboardHidden|orientation">

или

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

6

Чтобы заблокировать экран по коду, вы должны использовать фактическое вращение экрана (0, 90, 180, 270) и знать его естественное положение, в смартфоне естественное положение будет портретным, а в планшете - это будет пейзаж.

Вот код (методы блокировки и разблокировки), он был протестирован на некоторых устройствах (смартфоны и планшеты) и отлично работает.

public static void lockScreenOrientation(Activity activity)
{   
    WindowManager windowManager =  (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE);   
    Configuration configuration = activity.getResources().getConfiguration();   
    int rotation = windowManager.getDefaultDisplay().getRotation(); 

    // Search for the natural position of the device    
    if(configuration.orientation == Configuration.ORIENTATION_LANDSCAPE &&  
       (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) ||  
       configuration.orientation == Configuration.ORIENTATION_PORTRAIT &&   
       (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270))   
    {   
        // Natural position is Landscape    
        switch (rotation)   
        {   
            case Surface.ROTATION_0:    
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);    
                break;      
            case Surface.ROTATION_90:   
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); 
            break;      
            case Surface.ROTATION_180: 
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); 
                break;          
            case Surface.ROTATION_270: 
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 
                break;
        }
    }
    else
    {
        // Natural position is Portrait
        switch (rotation) 
        {
            case Surface.ROTATION_0: 
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 
            break;   
            case Surface.ROTATION_90: 
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 
            break;   
            case Surface.ROTATION_180: 
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); 
                break;          
            case Surface.ROTATION_270: 
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); 
                break;
        }
    }
}

public static void unlockScreenOrientation(Activity activity)
{
    activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}

какой параметр следует передать как деятельность?
ПОЖАЛУЙСТА,

Активность, которая вызывает метод для блокировки / разблокировки его ориентации. Это публичный метод статической утилиты, который вызывается из разных действий.
PoOk

1
Прекрасно работает, но, серьезно, Android, почему мы должны делать все это *** только для ориентации экрана блокировки? !!!
Cocorico

да. Этот блокирует ориентацию, как мы делаем в манифесте. Это предотвратит активацию onConfigurationChanged. Есть ли метод, который блокирует пользовательский интерфейс в альбомной и по-прежнему вызывает onConfigurationChanged. Точно так же, как приложение камеры в Android делает
Ajith Memana

В SDK 18+ есть флаг SCREEN_ORIENTATION_LOCKED, который, кажется, работает, но вы все равно хотите использовать приведенный выше код для поддержки каждого устройства
DominicM

2

В Visual Studio Xamarin:

  1. Добавить:

using Android.Content.PM; вам список пространств имен деятельности.

  1. Добавить:

[Activity(ScreenOrientation = Android.Content.PM.ScreenOrientation.Portrait)]

как атрибут для вашего класса, вот так:

[Activity(ScreenOrientation = ScreenOrientation.Portrait)]
public class MainActivity : Activity
{...}

Этот вопрос касается Android, а не Xamarin.Android
Тревор Харт


0

Обратите внимание, что ни один из методов сейчас не работает!

В Android Studio 1 одним простым способом является добавление android:screenOrientation="nosensor".

Это эффективно блокирует ориентацию экрана.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.