Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Xamarin Forms on iOS How To Set Screen Orientation for Page?

So the title says it all. Im concerned at this point with iOS. I have tried to sue a custom renderer for my base page "LandscapeContentPage" which would hopefully force it to be rendered as landscape. I have been unsuccessful.

I attempted to use a hack I found where in ViewDidAppear you present a "fake" UIViewController that overrides the GetSupportedInterfaceOrientations to only return Landscape. This sort of works. The meat looks like this:

var c = new LandscapeViewController();
c.View.BackgroundColor = UIColor.Cyan;

await PresentViewControllerAsync(c, false);
await DismissViewControllerAsync(false);

If I set a breakpoint at the Dismiss line I can see in the simulator that the view did change to landscape, the simulator window actually rotates on its own. When I continue either an error is thrown about view transitions or the ViewDidAppear fires again and the original page is displayed in portrait orientation.

So, I'm more or less lost at this point. I have tried so many different things and had zero success. I can't figure out why there isn't an out of the box mechanism for this. Such an expensive toolset/framework seems incomplete without orientation handling.

Thanks.

like image 290
jmichas Avatar asked Mar 15 '15 06:03

jmichas


People also ask

What is orientation in xamarin forms?

Xamarin. Android supports several options for specifying orientation: Landscape – forces the application orientation to be landscape, regardless of sensor data. Portrait – forces the application orientation to be portrait, regardless of sensor data.

How do I change the orientation of a Web page?

Change part of a document to landscape Select the content that you want on a landscape page. Go to Layout, and open the Page Setup dialog box. Select Landscape, and in the Apply to box, choose Selected text.


3 Answers

The approach from Chad Bonthuys works like a charms. I've got two litte additions.

Android: If you rotate and leave the view, the other views now will be in the requested orientation as well. Just call

GetActivity().RequestedOrientation = ScreenOrientation.Unspecified;

on leaving. That will allow other views to rotate again.

iOS: The view will be rotated, but the user is still able to rotate it back. You can lock it if you override the

GetSupportedInterfaceOrientations()

on

AppDelegate.cs

public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations (UIApplication application, [Transient] UIWindow forWindow)
{
    if (Xamarin.Forms.Application.Current == null || Xamarin.Forms.Application.Current.MainPage == null)
    {
        return UIInterfaceOrientationMask.All;
    }

    var mainPage = Xamarin.Forms.Application.Current.MainPage;

    if (mainPage is YOUR_VIEW||
            (mainPage is NavigationPage && ((NavigationPage)mainPage).CurrentPage is YOUR_VIEW) ||
            (mainPage.Navigation != null && mainPage.Navigation.ModalStack.LastOrDefault () is YOUR_VIEW))
    {
        return UIInterfaceOrientationMask.Landscape;
    }

    return UIInterfaceOrientationMask.All;
}

Just replace YOUR_VIEW with your ContentPage you want to lock

like image 200
Murolack Avatar answered Oct 18 '22 02:10

Murolack


I used a dependency service for this.

https://developer.xamarin.com/guides/cross-platform/xamarin-forms/dependency-service/

Interface

public interface IOrientationHandler
{
    void ForceLandscape();

    void ForcePortrait();
}

Calling the interface from Forms

DependencyService.Get<IOrientationHandler>().ForceLandscape();

IOS Implementation

public class OrientationHandlerImplementation : IOrientationHandler
    {
        public void ForceLandscape()
        {
            UIDevice.CurrentDevice.SetValueForKey(new NSNumber((int)UIInterfaceOrientation.LandscapeLeft), new NSString("orientation"));
        }

        public void ForcePortrait()
        {
            UIDevice.CurrentDevice.SetValueForKey(new NSNumber((int)UIInterfaceOrientation.Portrait), new NSString("orientation"));
        }
    }

Android Implementation

public class OrientationHandler : BaseDependencyImplementation, IOrientationHandler
{
    public void ForceLandscape()
    {
        GetActivity().RequestedOrientation = ScreenOrientation.Landscape;
    }

    public void ForcePortrait()
    {
        GetActivity().RequestedOrientation = ScreenOrientation.Portrait;
    }
}

Edit - Added Base Dependency Implementation as per request

BaseDependency Implementation

 public class BaseDependencyImplementation : Object
    {
        public Activity GetActivity()
        {
            var activity = (Activity)Forms.Context;
            return activity;
        }
    }

If you want to set orientation for the whole app it can be done in the app settings / manifest file.

like image 25
Chad Bonthuys Avatar answered Oct 18 '22 01:10

Chad Bonthuys


The below solution works with out dependency service.

Suppose if we want to have three pages and for second page only we need to have landscape orientation, below code is working for me.

Add below method to AppDelegate.cs

public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations(UIApplication application, [Transient] UIWindow forWindow)
        {
            if (Xamarin.Forms.Application.Current == null || Xamarin.Forms.Application.Current.MainPage == null)
            {
                return UIInterfaceOrientationMask.Portrait;
            }

            var mainPage = Xamarin.Forms.Application.Current.MainPage;

            if (mainPage is SecondPage ||
                    (mainPage is NavigationPage && ((NavigationPage)mainPage).CurrentPage is SecondPage) ||
                    (mainPage.Navigation != null && mainPage.Navigation.ModalStack.LastOrDefault() is SecondPage))
            {
                return UIInterfaceOrientationMask.Landscape;
            }

            return UIInterfaceOrientationMask.Portrait;
        }

Add a custom renderer to change the orientation.

[assembly: ExportRenderer(typeof(MainPage), typeof(MainPagePageRenderer))]
namespace App2.iOS
{
    public class MainPagePageRenderer : PageRenderer
    {
        public override void ViewWillDisappear(bool animated)
        {
            base.ViewWillDisappear(animated);
            UIDevice.CurrentDevice.SetValueForKey(NSNumber.FromNInt((int)(UIInterfaceOrientation.LandscapeLeft)), new NSString("orientation"));
        }
    }
}

Here, we have three pages MainPage, SecondPage and ThirdPage in the app and we are trying to fix landscape orientation to SecondPage. We need to create a custom renderer for MainPage since we need to change the orientation when going to SecondPage. We fix the orientation in AppDelegate for SecondPage so it won't change the orientation even if we rotate the phone.

Now, the portrait orientation is locked for MainPage and ThirdPage and the landscape for SecondPage.

We may need to create as many as custom renderers for each page to fix orientation.

Thanks.

like image 31
Ramesh Avatar answered Oct 18 '22 03:10

Ramesh