ChatGPT解决这个技术问题 Extra ChatGPT

How do I disable orientation change on Android?

I have an application that I just would like to use in portrait mode, so I have defined android:screenOrientation="portrait" in the manifest XML. This works OK for the HTC Magic phone (and prevents orientation changes on other phones as well).

But I have a problem with the HTC G1 phone as I open the hardware QWERTY keyboard (not the virtual keyboard). My activity stays in portrait mode, but it seems to get restarted and loses all its states. This does not happen with the HTC Hero version.

My application is quite big, so I don't want it to restart and lose all its states when the keyboard is opened. How can I prevent that?


P
Prags

Update April 2013: Don't do this. It wasn't a good idea in 2009 when I first answered the question and it really isn't a good idea now. See this answer by hackbod for reasons:

Avoid reloading activity with asynctask on orientation change in android

Add android:configChanges="keyboardHidden|orientation" to your AndroidManifest.xml. This tells the system what configuration changes you are going to handle yourself - in this case by doing nothing.

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

See Developer reference configChanges for more details.

However, your application can be interrupted at any time, e.g. by a phone call, so you really should add code to save the state of your application when it is paused.

Update: As of Android 3.2, you also need to add "screenSize":

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

From Developer guide Handling the Configuration Change Yourself

Caution: Beginning with Android 3.2 (API level 13), the "screen size" also changes when the device switches between portrait and landscape orientation. Thus, if you want to prevent runtime restarts due to orientation change when developing for API level 13 or higher (as declared by the minSdkVersion and targetSdkVersion attributes), you must include the "screenSize" value in addition to the "orientation" value. That is, you must declare android:configChanges="orientation|screenSize". However, if your application targets API level 12 or lower, then your activity always handles this configuration change itself (this configuration change does not restart your activity, even when running on an Android 3.2 or higher device).


Just to add to this and be really explicit, Android can mercilessly kill your application at any time, regardless of orientation changes, so you should use onPause() and onSaveInstanceState() to save state, no matter what.
The 3.2 update was very useful and was what was blocking me. I had no idea why my onConfigurationChanged handler wasn't firing and this was it. Thanks!
the third param - screenSize cannot be found in 2.3.x , should i change to screenLayout?
@Lumma No, "screenSize" is only needed for Android 3.2 and newer. What level API are you targeting? I think you only need to add it if you are targeting level 13 or above. I will update the answer to clarify.
Just in case it is helpful to other people, I have found you both <...android:configChanges="orientation"...> to override changes and <...android:screenOrientation="portrait"...> to define the default.
C
Community

You need to modify AndroidManifest.xml as Intrications (previously Ashton) mentioned and make sure the activity handles the onConfigurationChanged event as you want it handled. This is how it should look:

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

As noted by Dmitry Zaitsev, it is better to put the setRequestedOrientation() in onCreate().
Does not onConfigurationChanged() get called before onCreate() if so setting orientation before setting contentViews in oncreate is better approach, setting configuration where it belongs is also cleaner so this answer still stands good.
m
m00sey

I've always found you need both

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

D
Dmitry Zaytsev

As said, set android:configChanges of your Activity (in manifest file) to keyboardHidden|orientation and then:

1) Override onConfigurationChanged()

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

2) Add this line to your activity's onCreate()

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

It's better than add same line to onConfigurationChanged, because your app will turn to portrait mode and then back to landscape (it will happen only one time, but it's annoying).

Also you can set android:screenOrientation="nosensor" for your activity (in manifest). But using this way you're a not able to handle orientation changes at all.


What should I do if I want to avoid re-creation of the activity upon rotation, yet I wish to allow the user to lock the orientation via the OS's settings ?
@androiddeveloper that a separate question, which already has an answer: stackoverflow.com/a/14771495/926907
Your link is about changing the content by myself when the configuration changes, yet I wish to avoid the rotation of the activity (so that it will stay exactly the way it looks like) in case the user has chosen to lock the orientation via the OS's settings (available on some devices via the quick-settings, in the notification drawer).
@androiddeveloper ah, I think I understood. Then take a look at this link: developer.android.com/reference/android/… According to the docs, default orientation should already take user preference into account. If that's not the case, then I suspect that it's a OS specific behavior. I would be glad to hear about your results - now I'm also interested in it :)
I know the default will handle the user's preferences, but it also re-creates the activity when you rotate the screen, which is something I don't want to have.
M
Muhammad Aamir Ali

Use this..

    android:screenOrientation="portrait"

N
Numenor

In OnCreate method of your activity use this code:

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

Now your orientation will be set to portrait and will never change.


With that you don't prevent restarting the activity every time the orientation configuration changes.
Also, this doesn't work if you enter the Activity from a previous Activity in landscape orientation.
P
Peter Mortensen

In the AndroidManifest.xml file, for each activity you want to lock add the last screenOrientation line:

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

Or android:screenOrientation="landscape".


P
Peter Mortensen

In your androidmanifest.xml file:

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

or

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

P
PoOk

To lock the screen by code you have to use the actual rotation of the screen (0, 90, 180, 270) and you have to know the natural position of it, in a smartphone the natural position will be portrait and in a tablet, it will be landscape.

Here's the code (lock and unlock methods), it has been tested in some devices (smartphones and tablets) and it works great.

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

what paramater should be passed as activity?
The Activity that calls the method to lock/unlock its orientation. That's a public static utility method to be called from differents Activities.
Works great, but, seriously, Android, why do we have to do all that s*** just for lock screen orientation ?!!!
yes. This one locks the orientation as we do in the manifest. This will prevent the onConfigurationChanged from being invoked anymore. Is there a method that locks UI to Landscape and still invokes the onConfigurationChanged. Just like the camera app in android does
There is a SCREEN_ORIENTATION_LOCKED flag on SDK 18+ which seems to work but you'd still want to use the code above to support every device
P
Peter Mortensen

Add

android:configChanges="keyboardHidden|orientation|screenSize" 

to your manifest.


inside your tag
R
Roy Doron

In Visual Studio Xamarin:

Add:

using Android.Content.PM; to you activity namespace list.

Add:

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

as an attribute to you class, like that:

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

This question is asking about Android, not Xamarin.Android
E
Elaa_sekar

You can simply use like below in the application class if you want only PORTRAIT mode for all activities in your app.

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) {

        }

    })

}

}


P
Peter Mortensen

Please note, none of the methods seems to work now!

In Android Studio 1 one simple way is to add android:screenOrientation="nosensor".

This effectively locks the screen orientation.