Control single page orientation and view rotation in Xamarin Forms

Viewed 2534

in our project we are going to lock app in portrait mode, no problem so far. Now we would like to have the possibility to rotate only some specific pages or content (to display larger plots). I've googled the many threads on this issue but didn't find a clear solution. Is there any clean way for specify orientation on page basis for both Andoid and Ios?

We where also investigating the possibility to just rotate the plot view but we are having problems in sizing it; No matter what i specify for height and width request the graph is always displayed with containing page width and height. We tried both to invert the size before rotating:

rotatedView.WidthRequest = Height;
rotatedView.HeightRequest = Width;
rotatedView.Rotate(90)
contentView.Content = rotatedView;

And drawing it smaller by imposing the aspect ratio it would have after rotation and then scaling:

rotatedView.WidthRequest = Width;
double ratio = Height / Width;
rotatedView.HeightRequest = Width / ratio;
rotatedView.Rotation = 90;
rotatedView.ScaleTo(ratio)
contentView.Content = graphRot;

The view after rotation keeps the same aspect ratio of original page with Width being equal to page Height and viceversa.

Any hint would be much appreciated

UPDATE

Regarding View rotation i was able to do it by placing all stuff in a relative layout. This way i was able to freely define view size being equal to rotated container size.

2 Answers

I have implemented a solution in the application I am working on. My use case was I wanted to lock in portrait orientation, except if I was in the Video Player. The code below is how I am accomplishing this task.

For iOS:

You will need to override GetSupportedInterfaceOrientations in your AppDelegate.cs and put some logic in there.

public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations(UIApplication application, UIWindow forWindow)
{
    UIInterfaceOrientationMask supportedOrientation;

    if (_AllowRotations == true)
    {
        supportedOrientation = UIInterfaceOrientationMask.AllButUpsideDown;
    }
    else
    {
        supportedOrientation = UIInterfaceOrientationMask.Portrait;
    }

    return supportedOrientation;
}

For Android:

To set the correct flags on Android, you will need a method in your LaunchActivity.cs where you set the appropriate flags.

if (allowRotations == true)
{
    RequestedOrientation = ScreenOrientation.Sensor;
}
else
{
    RequestedOrientation = ScreenOrientation.Portrait;
}

I would suggest putting these in some sort of dependency service if you would like to call these from Xamarin.Forms. My allowrotations variables in each class are set from an event that I am using from my VideoPlayerRenderer, but you could set them from the dependency service also.

I worked around the view rotation problem this way:

    /// <summary>
    /// Rotates an element by 90 or 270 degrees. It is required that you put a RelativeLayout (no parameters needed)
    /// around it and call this method on the element (i.e. in onAppearing).
    /// </summary>
    private void SetLandscape(VisualElement element, bool ccw = false)
    {
        element.Rotation = ccw ? 270.0 : 90.0;
        RelativeLayout.SetHeightConstraint(element, Constraint.RelativeToParent(layout => layout.Width));
        RelativeLayout.SetWidthConstraint(element, Constraint.RelativeToParent(layout => layout.Height));
        RelativeLayout.SetYConstraint(element, Constraint.RelativeToParent(layout => (layout.Height - layout.Width) / 2));
        RelativeLayout.SetXConstraint(element, Constraint.RelativeToParent(layout => (layout.Width - layout.Height) / 2));
    }

Since delegates are used, this even keeps working on layout changes.

Constraints can also be defined in Xaml, however, the subtraction would be tricky, so I found another way by manipulating the rotation anchors. Looks funny but works - at the end I used this:

<RelativeLayout>
  <Grid Rotation="90" AnchorX="0" AnchorY="0"
        RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width}"
        RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height}"
        RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width}">

  </Grid>
</RelativeLayout>
Related