Eduardo Rosas' Blog

Learn Azure, Xamarin, WPF, and more!

Handling Landscape and Portrait Modes in Xamarin Forms

In the previous post, I showed you how you could handle multiple states for a specific element using the VisualStateManager and defining various groups and VisualStates.

In this post, we will use this same feature to change the UI of an example application so that it hides a title when the device is on portrait mode, so there is more space for the main component of the interface, which will be a ListView.

advertisement-communication-device-949602.jpg

Initial Setup

If you want to follow this example with my code, start by cloning this repo from my GitHub, otherwise, you can continue with your application.

Notice that in that repo there are two branches in addition to the master branch, make sure you clone or download the "initial" branch. The "final" branch contains all the initial code plus the code that is added in this post.

If you are using my example, you will notice that the project lists 30 categories inside a ListView, and that there is a large title at the top of the UI. While in portrait mode, this looks fine, however, if you switch the device (or simulator) to landscape mode, you will notice that the title uses a considerable amount of the available space.

Let's solve this issue by implementing a couple of Visual States, two new Visual States in addition to the common states that could be defined (Normal, Disabled and Focus are the existent common states, but in this example, we won't use them).

Since I have already explained VisualStates in the previous post, I will not get into a lot of details here, but notice that all I'm doing is changing the visibility of the Label depending on the State.

<Label Text="Categories"
       TextColor="Coral"
       FontSize="30"
       FontAttributes="Bold"
       Margin="16,0">
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup Name="OrientationStates">
            <VisualState Name="Portrait">
                <VisualState.Setters>
                    <Setter Property="IsVisible" Value="true"/>
                </VisualState.Setters>
            </VisualState>
            <VisualState Name="Landscape">
                <VisualState.Setters>
                    <Setter Property="IsVisible" Value="false"/>
                </VisualState.Setters>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
</Label>

Using the Custom States

Since we are defining a couple of custom states (and not using the common states), we will need to handle the changes manually. Handling the changes means that we will need to let the VisualStateManager know when is it that we use an individual State over the other.

Depending on the states that you are using, this could happen in different ways, but for this example, we will need to know when the UI's orientation changes from portrait to landscape.

Knowing when the orientation changes

To achieve this, we can use the Page's SizeChanged event. Every time the Page changes orientation, its width and height change; hence the SizeChanged event is fired. So, let's create an event handler.

public MainPage()
{
    InitializeComponent();

    Xamarin.Forms.PlatformConfiguration.iOSSpecific.Page.SetUseSafeArea(this, true);

    PopulateCategories();

    SizeChanged += MainPage_SizeChanged;
}

void MainPage_SizeChanged(object sender, EventArgs e)
{

}

Inside the event handler, is where we can evaluate the size to know whether the orientation is landscape or portrait, this can happen with a quick comparison between the height and the width. If the width is greater than the height, that means the device is on landscape mode. I will immediately assign a value to a new variable depending on the result of the evaluation, making sure that the value matches the names of the VisualStates that I defined earlier.

string visualState = Width > Height ? "Landscape" : "Portrait";

Now the visualState variable contains the name of the VisualState that has to be used for the current scenario, let's use that value to tell the VisualStateManager what to do.

Setting the VisualState

Since I will set the VisualState of the label, I need access to it. So I will name that label from the XAML file (I called it titleLabel), and use it from the SizeChanged event handler like this:

VisualStateManager.GoToState(titleLabel, visualState);

What this code does is tell the VisualStateManager that a specific element will use one of the States that have been defined. The GoToState method then will request the item that will change its state (the titleLabel in this scenario), and the name of the VisualState that will be used (the value that we already have inside the visualState variable).

That is it; our application will now hide the title when the device is on landscape mode.

So, what do you think? Is this useful? Will you be using this anytime soon?