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

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

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

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

14 ответов

Решение

Обновление апрель 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" в дополнение к значению "ориентации". То есть вы должны объявить android:configChanges="orientation|screenSize", Однако, если ваше приложение предназначено для уровня API 12 или ниже, то ваша активность всегда сама обрабатывает это изменение конфигурации (это изменение конфигурации не перезапускает вашу активность, даже при работе на устройстве Android 3.2 или выше).

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

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

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

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

Как сказано, установить 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:screenOrientation="portrait"

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

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

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

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

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

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

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

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

или же

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

Чтобы заблокировать экран по коду, вы должны использовать фактическое вращение экрана (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);
}

В Visual Studio Xamarin:

  1. Добавлять:

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

  1. Добавлять:

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

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

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

Вы можете просто использовать, как показано ниже, в классе приложения, если вам нужен только режим PORTRAIT для всех действий в вашем приложении.

      class YourApplicationName : Application() {

override fun onCreate() {
    super.onCreate()

    registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {

        override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
            activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
        }

        override fun onActivityStarted(activity: Activity) {

        }

        override fun onActivityResumed(activity: Activity) {

        }

        override fun onActivityPaused(activity: Activity) {

        }

        override fun onActivityStopped(activity: Activity) {

        }

        override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {

        }

        override fun onActivityDestroyed(activity: Activity) {

        }

    })

}

}

Добавлять

android:configChanges="keyboardHidden|orientation|screenSize" 

к вашему манифесту.

Старое решение:

      @SuppressLint("SourceLockedOrientationActivity")
fun Activity?.lockScreenOrientation() {
    this ?: return

    val display: Display = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        display
    } else {
        @Suppress("DEPRECATION")
        windowManager.defaultDisplay
    } ?: return

    val width: Int = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        window.windowManager.currentWindowMetrics.bounds.width()
    } else {
        @Suppress("DEPRECATION")
        display.width
    }
    val height: Int = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        window.windowManager.currentWindowMetrics.bounds.height()
    } else {
        @Suppress("DEPRECATION")
        display.height
    }

    when (display.rotation) {
        // 0
        Surface.ROTATION_0 -> {
            requestedOrientation = if (height > width) {
                ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
            } else {
                ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
            }
        }
        // 1
        Surface.ROTATION_90 -> {
            requestedOrientation = if (width > height) {
                ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
            } else {
                ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT
            }
        }
        // 2
        Surface.ROTATION_180 -> {
            requestedOrientation = if (height > width) {
                ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT
            } else {
                ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
            }
        }
        // 3
        Surface.ROTATION_270 -> {
            requestedOrientation = if (width > height) {
                ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE
            } else {
                ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
            }
        }
    }
}

Новое решение:

      fun Activity?.lockScreenOrientation() {
    this ?: return
    requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LOCKED
}

Разблокировать решение:

      fun Activity?.unlockScreenOrientation() {
    this ?: return
    requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
}

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

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

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

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