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
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
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.
@VictorHGarcia It's from the normal Xamarin.Forms Framework. U can use it by adding
Using Xamarin.Forms
or just type it outswitch(Xamarin.Forms.Device.Idiom)
@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.
@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
@RaphaelSchindler, thank you for sharing your answer, it has been very helpful to me.
This solution locks entry app, right? How to lock just one specific page?
Thx for this amazing solution!
@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.
@Zontag For WP 8.1, update
DisplayInformation.AutoRotationPreferences
on each page. For Android, updateRequestedOrientation
. iOS is the hardest as most things online do not work. UseGetSupportedInterfaceOrientations
inAppDelegate.cs
and return the correct orientation based on current page type.@AdrianKnight Does your solution for iOS automatically rotate the screen?
@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 yourGetSupportedInterfaceOrientations
. Compare current page to a page type and return the correct mask instead of doingswitch(Device.Idiom)
.@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!
@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.@AdrianKnight Amazing! Thax a lot!
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
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)@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
A Xamarin.Forms app for Android consists of one Activity. What you want is Pagewise not Activitywise
Oh, i did not mention that "detail" sorry, i need it without Xamarin.Forms
@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
No, i tried almost everything but still nothing, error is persistent.
Thank you for your fast answer anyway
@Jefimijana Did you solve the problem? I have the same exception while trying to load the application from background.
Yes and here is the solution that worked for me:
You can use
protected override async void OnCreate(){ . . . }
and see if it worksHope it helped
Regards
@RaphaelSchindler cant we write Android like ISO code, simply
Is it not feasible?
@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
Great article, just copy/pasted and it worked, thank you!
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);
@Baraa_Aljabban Nice. Good finding
Thanks, that worked for me!