【问题标题】:How do I disable orientation change on Android?如何在 Android 上禁用方向更改?
【发布时间】:2010-12-03 11:30:37
【问题描述】:

我有一个应用程序,我只想在纵向模式下使用,所以我定义了 清单 XML 中的 android:screenOrientation="portrait"。这适用于HTC Magic 手机(也可以防止其他手机上的方向更改)。

但是当我打开硬件QWERTY keyboard(不是虚拟键盘)时,HTC G1 电话出现问题。我的活动保持纵向模式,但它似乎重新启动并失去了所有状态。 HTC Hero 版本不会发生这种情况。

我的应用程序很大,所以我不希望它在打开键盘时重新启动并丢失所有状态。我怎样才能防止这种情况发生?

【问题讨论】:

标签: android android-activity android-orientation


【解决方案1】:

2013 年 4 月更新:不要这样做。 2009 年我第一次回答这个问题时,这不是一个好主意,现在真的不是一个好主意。出于以下原因,请参阅 hackbod 的答案:

Avoid reloading activity with asynctask on orientation change in 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">

来自开发者指南 Handling the Configuration Change Yourself

注意:从 Android 3.2(API 级别 13)开始,“屏幕尺寸” 当设备在纵向和横向之间切换时也会发生变化 方向。因此,如果您想防止运行时重新启动 为 API 级别 13 或更高级别(如 由 minSdkVersion 和 targetSdkVersion 属性声明),你 除了“方向”之外,还必须包含“screenSize”值 价值。也就是说,您必须声明 android:configChanges="orientation|screenSize"。但是,如果您的 应用程序以 API 级别 12 或更低级别为目标,那么您的活动始终 自行处理此配置更改(此配置更改 不会重新启动您的活动,即使在 Android 3.2 或 更高的设备)。

【讨论】:

  • 只是补充一点,明确一点,Android 可以随时无情地杀死你的应用程序,无论方向如何变化,所以你应该使用 onPause() 和 onSaveInstanceState() 来保存状态,不管什么。
  • 3.2 更新非常有用,是阻碍我的原因。我不知道为什么我的 onConfigurationChanged 处理程序没有触发,就是这样。谢谢!
  • 第三个参数 - screenSize 在 2.3.x 中找不到,我应该更改为 screenLayout 吗?
  • @Lumma 不,“screenSize”仅适用于 Android 3.2 及更高版本。您的目标是什么级别的 API?我认为您只需要在目标为 13 级或以上时添加它。我将更新答案以澄清。
  • 以防万一它对其他人有帮助,我发现你们两个都 来覆盖更改和 定义默认值。
【解决方案2】:

您需要修改 AndroidManifest.xml,如 Intrications(之前的 Ashton)所提到的,并确保活动按您希望的方式处理 onConfigurationChanged 事件。它应该是这样的:

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

【讨论】:

  • 正如 Dmitry Zaitsev 所说,最好将 setRequestedOrientation() 放在 onCreate() 中。
  • 不会在onCreate() 之前调用onConfigurationChanged() 如果在oncreate 中设置contentViews 之前设置方向是更好 的方法,在它所属的位置设置配置也是更干净 所以这个答案仍然很好。
【解决方案3】:

我一直发现你两者都需要

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

【讨论】:

    【解决方案4】:

    如前所述,将您的活动(在清单文件中)的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"(在清单中)。 但是使用这种方式你根本无法处理方向变化。

    【讨论】:

    • 如果我想避免在旋转时重新创建活动,但我希望允许用户通过操作系统的设置锁定方向,我应该怎么做?
    • @androiddeveloper 这是一个单独的问题,已经有了答案:stackoverflow.com/a/14771495/926907
    • 您的链接是关于在配置更改时我自己更改内容,但我希望避免活动的轮换(以便它保持原样)以防用户有选择通过操作系统的设置锁定方向(在某些设备上通过通知抽屉中的快速设置可用)。
    • @androiddeveloper 啊,我想我明白了。然后看看这个链接:developer.android.com/reference/android/… 根据文档,默认方向应该已经考虑到用户偏好。如果不是这种情况,那么我怀疑这是操作系统特定的行为。我很高兴听到你的结果 - 现在我也对它感兴趣:)
    • 我知道默认会处理用户的偏好,但它也会在您旋转屏幕时重新创建活动,这是我不想拥有的。
    【解决方案5】:

    使用这个..

        android:screenOrientation="portrait"
    

    【讨论】:

      【解决方案6】:

      在您的活动的 OnCreate 方法中使用以下代码:

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

      现在您的方向将设置为纵向并且永远不会改变。

      【讨论】:

      • 这样您就不会在每次方向配置更改时阻止重新启动活动。
      • 另外,如果您从以前的 Activity 横向输入 Activity,这将不起作用。
      【解决方案7】:

      在 AndroidManifest.xml 文件中,为每个要锁定的活动添加最后一行 screenOrientation

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

      android:screenOrientation="landscape"

      【讨论】:

        【解决方案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);
        }
        

        【讨论】:

          【解决方案9】:

          要通过代码锁定屏幕,您必须使用屏幕的实际旋转(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);
          }
          

          【讨论】:

          • 什么参数应该作为活动传递?
          • 调用方法来锁定/解锁其方向的活动。这是从不同的活动中调用的公共静态实用程序方法。
          • 效果很好,但是,说真的,Android,为什么我们必须为锁定屏幕方向做所有这些事情?!!!
          • 是的。就像我们在清单中所做的那样,这会锁定方向。这将阻止 onConfigurationChanged 被调用。是否有一种方法可以将 UI 锁定到 Landscape 并仍然调用 onConfigurationChanged。就像 android 中的相机应用一样
          • SDK 18+ 上有一个 SCREEN_ORIENTATION_LOCKED 标志似乎可以工作,但您仍然希望使用上面的代码来支持每个设备
          【解决方案10】:

          在 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
          【解决方案11】:

          添加

          android:configChanges="keyboardHidden|orientation|screenSize" 
          

          到您的清单。

          【讨论】:

          • 在你的 标签内
          【解决方案12】:

          请注意,这些方法现在似乎都不起作用!

          Android Studio 1 中,一种简单的方法是添加 android:screenOrientation="nosensor".

          这有效地锁定了屏幕方向。

          【讨论】:

            【解决方案13】:

            如果您只希望应用程序中的所有活动都使用 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) {
            
                    }
            
                })
            
            }
            

            }

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-04-06
              • 2018-04-09
              • 2012-10-21
              • 1970-01-01
              • 2018-10-29
              相关资源
              最近更新 更多