Adaptive UI with Xamarin.Forms

Adrian Stevens

Xamarin.Forms has supported iOS, Android, and Windows for a long time. We’ve also added new platforms to keep up with the changing landscape, such as Tizen and macOS, with Linux and Windows WPF on the horizon. These platforms run on a wide variety of devices including phones, tablets, desktops, and TVs. This presents an interesting challenge for us as developers; how do we design an adaptive UI that intelligently scales and makes sense on each idiom it’s presented on?

Respond to Screen Size

By default, Xamarin.Forms Layouts and Controls are designed to be responsive and will often grow and shrink to take advantage of the available screen space. If more control is needed, the Xamarin.Forms Page class has a SizeChanged event we can use to determine the available screen-size at runtime. This event is raised when the Page is displayed, allowing us to adjust or change our Page’s UI based on the Width or Height of the screen.

public partial class MainPage : ContentPage
{
   public MainPage()
   {
      InitializeComponent();
      SizeChanged += MainPageSizeChanged;
   }

   void MainPageSizeChanged(object sender, EventArgs e)
   {
      imgMonkey.WidthRequest = Math.Min(this.Width, 400);
   }
}

Respond to Orientation

We can use the SizeChanged event to respond to orientation changes. SizeChanged will be raised when the screen is rotated. We can determine the orientation by comparing the Page’s Width and Height properties.

 

public partial MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
        SizeChanged += MainPageSizeChanged;
    }

    void MainPageSizeChanged(object sender, EventArgs e)
    {
        bool isPortrait = this.Height > this.Width;
        stackPanel.Orientation = (isPortrait ? StackOrientation.Horizontal : StackOrientation.Vertical);
    }
}

Portrait and Landscape Orientations

Respond to Device Type

We often think about responsive and adaptive in terms of screen size, but we also need to respond to how the user interacts with the device. For instance, we use touch on mobile devices, and a mouse with a keyboard on a desktop PC. Xamarin.Forms provides a static Idiom property on the Device class that we can use to check the device type. Devices are sorted into four categories: Phone, Tablet, Desktop, and TV.

switch (Device.Idiom)
{
    case TargetIdiom.Desktop:
    ...
    case TargetIdiom.Phone:
    ...
    case TargetIdiom.Tablet:
    ...
    case TargetIdiom.TV:
    ...
}

 

We can use Device.Idiom to change the UI we present. We have several options you can use depending on a number of changes you need to make.

For small changes, like adjusting button sizes, we update the controls and layouts directly.

if (Device.Idiom == TargetIdiom.Desktop)
{
    buttonAbout.HeightRequest = 25;
    buttonAbout.WidthRequest = 40;
}
else
{
    buttonAbout.HeightRequest = 40;
    buttonAbout.WidthRequest = 70;
}

When you need to add or remove portions of your UI, Xamarin.Forms provides a ContentView which allows us to create composite controls. We define portions of reusable UI with behavior, and then decide which composite controls to display based on the Idiom. You can think of a ContentView as a partial Xamarin.Forms Page.

void AddColorPicker ()
{
    IMyColorPicker colorPicker;

    if (Device.Idiom == TargetIdiom.Desktop)
        colorPicker = new ColorPickerMouseView();
    else
        colorPicker = new ColorPickerTouchView();

    colorPicker.VerticalOptions = LayoutOptions.Start;
    colorPicker.ColorChanged += ColorPickerColorChanged;

    mainLayout.Children.Add(colorPicker)
}

 

When your UI changes are significant between device types, you can create multiple pages. We use Device.Idiom to decide which page to display or you can even use ContentViews within these pages to avoid duplicate code.

And If you’re using MVVM, you can define a single View Model that is used for each version of your Page, further reducing repeated code!

ContentPage page;

if(Device.Idiom == TargetIdiom.Desktop)
    page = new DetailsDesktopPage(new MyDetailViewModel(...));
else if(Device.Idiom == TargetIdiom.TV)
    page = new DetailsTVPage(new MyDetailViewModel(...));
else //Phone or Tablet
    page = new DetailsMobilePage(new MyDetailViewModel(...));

Navigation.PushAsync(page);

 

If you want to learn more about adaptive UI design, you can find excellent documentation here and here.

Head to the Xamarin University website for more great Xamarin training, including free Self-Guided courses!

Discuss this post on the forums.

1 comment

Discussion is closed. Login to edit/delete existing comments.

  • André Ziegler 0

    how can I do this in pure XAML to use previewer tools to modify the values without recompiling and redeploying the app all time until it looks good?

Feedback usabilla icon