如何在Android上禁用方向更改?


286

我有一个我只想在纵向模式下使用的应用程序,因此我在清单XML中定义了android:screenOrientation =“ portrait”。对于HTC Magic手机,这可以正常工作(并且还可以防止其他手机的方向更改)。

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

我的应用程序很大,所以我不希望它在打开键盘时重新启动并丢失所有状态。我该如何预防?


2
也可以尝试在这里查看: stackoverflow.com/questions/2366706/…–
安迪·温斯坦

Answers:


317

2013年4月更新:请勿执行此操作。在2009年,当我第一次回答这个问题时,这不是一个好主意,现在确实不是一个好主意。出于以下原因,请参阅hackbod的答案:

避免在Android中更改方向时使用asynctask重新加载活动

添加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属性所声明的)因方向更改而导致运行时重新启动,则除“ orientation”值外,还必须包括“ screenSize”值。也就是说,您必须声明 android:configChanges="orientation|screenSize"。但是,如果您的应用程序以API级别12或更低级别为目标,则您的活动始终会自行处理此配置更改(即使在Android 3.2或更高版本的设备上运行,此配置更改也不会重新启动您的活动)。


36
只是为了补充这一点并使其真正明确,Android可以随时毫不留情地杀死您的应用程序,而无需考虑方向变化,因此无论如何,您都应使用onPause()和onSaveInstanceState()保存状态。
Eric Mill

3.2更新非常有用,这正是阻止我前进的原因。我不知道为什么我的onConfigurationChanged处理程序没有触发,就是这样。谢谢!
sweetlilmre

第三个参数-screenSize在2.3.x中找不到,我应该更改为screenLayout吗?
死鱼2012年

2
@Lumma不,“ screenSize”仅适用于Android 3.2及更高版本。您定位的是什么级别的API?我认为,仅当您定位到13级或更高级别时,才需要添加它。我将更新答案进行澄清。
复杂

1
以防万一这对其他人有帮助,我发现您都<... android:configChanges =“ orientation” ...>可以覆盖更改,而<... android:screenOrientation =“ portrait” ...>定义默认值。
索格

96

您需要作为修改的AndroidManifest.xml Intrications(以前阿什顿)提到,确保活动处理的onConfigurationChanged事件,只要你想它来处理。它应该是这样的:

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

正如梅德扎伊采夫指出,最好是把setRequestedOrientation()onCreate()
Timmmm 2012年

3
如果这样在oncreate中设置contentViews之前设置方向是更好的方法,则不会onConfigurationChanged()在之前被调用,设置它所属的配置也更干净,因此此答案仍然有效。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"为自己的活动设置(在清单中)。但是使用这种方式根本无法处理方向变化。


如果要避免旋转时重新创建活动,但又希望允许用户通过OS的设置锁定方向,该怎么办?
Android开发人员

@androiddeveloper这是一个单独的问题,已经有一个答案:stackoverflow.com/a/14771495/926907
Dmitry Zaytsev 2014年

您的链接是关于在配置更改时由我自己更改内容的,但是我希望避免活动的旋转(以使其保持原样),以防用户选择通过OS锁定方向。设置(在某些设备上可通过通知抽屉中的快速设置获得)。
Android开发人员

@androiddeveloper啊,我想我明白了。然后看一下此链接:developer.android.com/reference/android/…根据文档,默认方向应该已经考虑了用户的偏好。如果不是这种情况,那么我怀疑这是特定于操作系统的行为。我很高兴听到您的结果-现在我对此也很感兴趣:)
Dmitry Zaytsev

我知道默认值将处理用户的首选项,但是当您旋转屏幕时,它也会重新创建活动,这是我不想要的。
Android开发人员


13

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

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

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


4
这样一来,您就不会阻止每次定向配置更改时重新启动活动。
AxeEffect 2013年

此外,如果您以横向方式从先前的“活动”中输入“活动”,则此操作无效。
w3bshark

10

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

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

什么参数应该作为活动传递?
WISHY 2014年

调用该方法以锁定/解锁其方向的Activity。这是一个公共的静态实用程序方法,可从“不同活动”中调用。
PoOk

1
效果很好,但是说真的,Android,为什么我们只需要为锁屏方向做所有这些事情?
Cocorico 2014年

是。就像我们在清单中所做的那样,这将锁定方向。这将防止onConfigurationChanged再次被调用。有没有一种方法可以将UI锁定为“风景”并仍然调用onConfigurationChanged。就像在Android上的相机应用做
阿吉特Memana

SDK 18+上有一个SCREEN_ORIENTATION_LOCKED标志,该标志似乎可以工作,但您仍想使用上面的代码来支持每台设备
DominicM 2015年

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
Trevor Hart,


0

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

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

这样可以有效锁定屏幕方向。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.