[Guide] Lock Screen-Orientation

RaphaelSchindlerRaphaelSchindler ✭✭✭USMember ✭✭✭

Hey,
Today I tried to lock the Screen-Orientation of the App I'm currently developing. I wanted to lock the Orientation on Phones to Portrait and on Tablets it have to be Landscape.

Normally I would create Layouts for Landscape and Portrait mode for both Idioms, but in this case that is not the way to go.
Think of Angry-Birds in Portrait Mode on a Phone. Yeah that would be a crappy experience :)

So I worked on that and was finally able to do it.

Now here's what I've done:

On Android you have to set those flags in MainActivity.cs:

[Activity(Label = "YourAppName", Icon = "@drawable/Icon", Theme = "@style/StandardTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]

And in the OnCreate you write those lines before base.OnCreate(bundle);

switch(Device.Idiom)
{
    case TargetIdiom.Phone:
        RequestedOrientation = ScreenOrientation.Portrait;
        break;
    case TargetIdiom.Tablet:
        RequestedOrientation = ScreenOrientation.Landscape;
        break;
}

So I tested this on my Tablet and hell yeah it worked. I couldn't change the Orientation anymore.
But then I tested it on my Phone and hell no it didn't worked :(

I searched for a few hours for a solution why it won't work and tested a lot of stuff that I found here in the forums or on SO.
And then I stumbled upon this SO Thread: Stack Overflow.
Here was the problem. It was my Phone! I have an Samsung Galaxy Note 2.
So I searched on the internet what is going on and found out that different devices ignoring the RequestedOrientation flag

Then I remember that in MainActivity.cs you can override this:

public override void OnConfigurationChanged(Android.Content.Res.Configuration newConfig)

The Configuration in here has a Orientation property which will give you access to the current Orientation

Now I hooked it up and got this solution:

public override void OnConfigurationChanged(Android.Content.Res.Configuration newConfig)
{
    base.OnConfigurationChanged(newConfig);

    switch(newConfig.Orientation)
    {
        case Orientation.Landscape:
            switch(Device.Idiom)
            {
                case TargetIdiom.Phone:
                    LockRotation(Orientation.Portrait);
                    break;
                case TargetIdiom.Tablet:
                    LockRotation(Orientation.Landscape);
                    break;
            }
            break;
        case Orientation.Portrait:
            switch(Device.Idiom)
            {
                case TargetIdiom.Phone:
                    LockRotation(Orientation.Portrait);
                    break;
                case TargetIdiom.Tablet:
                    LockRotation(Orientation.Landscape);
                    break;
            }
            break;
    }
}

private void LockRotation(Orientation orientation)
{
    switch(orientation)
    {
        case Orientation.Portrait:
            RequestedOrientation = ScreenOrientation.Portrait;
            break;
        case Orientation.Landscape:
            RequestedOrientation = ScreenOrientation.Landscape;
            break;
    }
}

Now everything worked as it should. Now even on my Galaxy Note 2 it didn't changed the Orientation anymore.

For iOS it was really simple compared to Android :) Just put this in your AppDelegate.cs

public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations(UIApplication application, UIWindow forWindow)
{
    switch(Device.Idiom)
    {
        case TargetIdiom.Phone:
            return UIInterfaceOrientationMask.Portrait;
        case TargetIdiom.Tablet:
            return UIInterfaceOrientationMask.Landscape;
        default:
            return UIInterfaceOrientationMask.Portrait;
    }
}

I hope this helps someone who is struggling with the same thing :)

Posts

  • Hassan.7945Hassan.7945 USMember

    Thanks for taking time out and providing us with a solution, I have just started looking for a solution to locking the rotation task and it was nice to see that the first post here was a solution and not an issue :).
    cheers

  • VictorHGarciaVictorHGarcia ✭✭ USUniversity ✭✭
    edited January 2016

    I'm pretty interested on this topic. However @RaphaelSchindler I'm having issues to understand from where the "Device" variable is coming from. Would you mind help me, or if possible share the MainActivity.cs full file for further reference?

    Note: I'm not using Xamarin.Forms.

    Thanks in advance.

  • RaphaelSchindlerRaphaelSchindler ✭✭✭ USMember ✭✭✭

    @VictorHGarcia It's from the normal Xamarin.Forms Framework. U can use it by adding Using Xamarin.Forms or just type it out

    switch(Xamarin.Forms.Device.Idiom)

  • VictorHGarciaVictorHGarcia ✭✭ USUniversity ✭✭

    @RaphaelSchindler is it safe to add Xamarin.Forms library to a project that is not Xamarin.Forms form the beginning? This project is platform specific: Normal PCL, Xamarin.iOS and Xamarin.Android.

  • RaphaelSchindlerRaphaelSchindler ✭✭✭ USMember ✭✭✭

    @VictorHGarcia If you're creating a normal Xamarin.Android project you should have a more direct access to the Device.Orientation, since Xamarin.Forms is just an abstract layer for them. That's something you have to look up in the Documentation of Xamarin.Android

  • Francisco_NievesFrancisco_Nieves USMember

    @RaphaelSchindler, thank you for sharing your answer, it has been very helpful to me.

  • ZontagZontag ✭✭ BRMember ✭✭

    This solution locks entry app, right? How to lock just one specific page?

    Thx for this amazing solution!

  • RaphaelSchindlerRaphaelSchindler ✭✭✭ USMember ✭✭✭

    @Zontag Yes, this is for the complete app. I couldn't come up with a good solution to just lock on page. At least not on iOS and WinPhone.

  • AdrianKnightAdrianKnight ✭✭✭✭ USMember ✭✭✭✭

    @Zontag For WP 8.1, update DisplayInformation.AutoRotationPreferences on each page. For Android, update RequestedOrientation. iOS is the hardest as most things online do not work. Use GetSupportedInterfaceOrientations in AppDelegate.cs and return the correct orientation based on current page type.

  • RaphaelSchindlerRaphaelSchindler ✭✭✭ USMember ✭✭✭

    @AdrianKnight Does your solution for iOS automatically rotate the screen?

  • AdrianKnightAdrianKnight ✭✭✭✭ USMember ✭✭✭✭

    @RaphaelSchindler My app starts in portrait mode. I only need to enable landscape for certain pages. AppDelegate.cs will detect page change and automatically rotate screen. I don't have access to my code now, but if I remember correctly, you need to edit your GetSupportedInterfaceOrientations. Compare current page to a page type and return the correct mask instead of doing switch(Device.Idiom).

  • ZontagZontag ✭✭ BRMember ✭✭

    @AdrianKnight I don't know how to call this specific platforms codes from my Xamarin Forms ContentPage. Any suggestion?

    Thank you very much for you time!

  • AdrianKnightAdrianKnight ✭✭✭✭ USMember ✭✭✭✭

    @Zontag You need to use DependencyService. See here https://developer.xamarin.com/guides/xamarin-forms/dependency-service/

    Create an interface in your PCL and then platform-specific implementations in your other projects. You'd typically invoke orientation change methods in OnAppearing() of each page.

  • ZontagZontag ✭✭ BRMember ✭✭

    @AdrianKnight Amazing! Thax a lot! :smiley:

  • JefimijanaJefimijana ✭✭ USMember ✭✭
    edited March 2016

    Is there any solution for locking just one Activity?

    I saw many posts that suggest setting orientation property inside AndroidManifest which can be done like

    [Activity(ScreenOrientation = ScreenOrientation.Landscape)]
        public class MyActivity : AppCompatActivity
        { ... }
    

    What i want to achieve is that i want to lock orientation for just one Activity only in case that user is using Phone, in case that he is using Tablet, both orientations should be supported and i suppose that this has to be done programmatically. (without Xamarin.Forms)

    I tried something similar to @RaphaelSchindler solution, but i am keep getting "Can not perform this action after onSaveInstanceState" and I am not sure what is causing this

    (interesting article about that one: (http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html)

  • RaphaelSchindlerRaphaelSchindler ✭✭✭ USMember ✭✭✭
    edited March 2016

    @Jefimijana Somewhere in the forum I wrote how to lock a single Page if I can remember correctly. If not just tell me and I will post it.

    Just for clarification :smile: A Xamarin.Forms app for Android consists of one Activity. What you want is Pagewise not Activitywise

  • JefimijanaJefimijana ✭✭ USMember ✭✭

    Oh, i did not mention that "detail" sorry, i need it without Xamarin.Forms

  • RaphaelSchindlerRaphaelSchindler ✭✭✭ USMember ✭✭✭
    edited March 2016

    @Jefimijana Hmm then I don't know if I can help you. Isn't this in the Xamarin.Android documents on developers.xamarin.com

    Maybe this will help http://stackoverflow.com/questions/3611457/android-temporarily-disable-orientation-changes-in-an-activity

  • JefimijanaJefimijana ✭✭ USMember ✭✭

    No, i tried almost everything but still nothing, error is persistent.

    Thank you for your fast answer anyway :)

  • 15mgm1515mgm15 ✭✭✭✭ USMember ✭✭✭✭

    @Jefimijana Did you solve the problem? I have the same exception while trying to load the application from background.

  • JefimijanaJefimijana ✭✭ USMember ✭✭
    edited June 2016

    Yes and here is the solution that worked for me:

    [Activity(ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize, 
                  ScreenOrientation = ScreenOrientation.Unspecified)]
    
    public class CustomActivity : Activity
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
                base.OnCreate(savedInstanceState);
    
                if (!isTablet(ApplicationContext))
                    RequestedOrientation = ScreenOrientation.Landscape;
    
                   . . .
         }
    
    
          public static bool isTablet(Context context)
          {
                ScreenLayout screenSize = context.Resources.Configuration.ScreenLayout & ScreenLayout.SizeMask;
                    bool tablet = false;
    
                    switch (screenSize)
                    {
                        case ScreenLayout.SizeXlarge:
                                tablet = true;
                                break;
                            case ScreenLayout.SizeLarge:
                                tablet = true;
                                break;
                        }
                        return tablet;
                    }
             } 
    
          public override void OnConfigurationChanged(Configuration newConfig)
          {
             base.OnConfigurationChanged(newConfig);
          }
    
    . . . 
    }
    

    You can use protected override async void OnCreate(){ . . . } and see if it works

    Hope it helped

    Regards

  • batmacibatmaci ✭✭✭✭✭ DEMember ✭✭✭✭✭

    @RaphaelSchindler cant we write Android like ISO code, simply

     switch (Xamarin.Forms.Device.Idiom)
                {
                    case Xamarin.Forms.TargetIdiom.Phone:
                        return Orientation.Portrait;
                    case Xamarin.Forms.TargetIdiom.Tablet:
                      return Orientation.Landscape;
                    default:
                        return Orientation.Portrait;
                }
    

    Is it not feasible?

  • RaphaelSchindlerRaphaelSchindler ✭✭✭ USMember ✭✭✭

    @batmaci If I remember this correctly this wouldn't work. But this thread is almost 2 years old so give it a try. Would be nice if you could report back so others can see it :)

  • IkramTurgunbaevIkramTurgunbaev USMember

    Great article, just copy/pasted and it worked, thank you!

  • Baraa_AljabbanBaraa_Aljabban Member

    now you can use an already existing plugin and save time
    Xamarin.Plugin.DeviceOrientation
    for me i want to make my login page on portrait mode only
    CrossDeviceOrientation.Current.LockOrientation(Plugin.DeviceOrientation.Abstractions.DeviceOrientations.Portrait);

  • RaphaelSchindlerRaphaelSchindler ✭✭✭ USMember ✭✭✭

    @Baraa_Aljabban Nice. Good finding

Sign In or Register to comment.