Skip to content

Instantly share code, notes, and snippets.

@stackunderflows
Last active June 21, 2019 11:23
Show Gist options
  • Save stackunderflows/f23a82112559eaf3579494ed54000cf6 to your computer and use it in GitHub Desktop.
Save stackunderflows/f23a82112559eaf3579494ed54000cf6 to your computer and use it in GitHub Desktop.
Xamarin - Use responsive breakpoints to have different property values depending on phone size and platform
<!-- Inspired from http://dkdevelopment.net/2018/06/24/xamarin-forms-responsive-xaml-properties/ -->
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MyApp.MainPage"
xmlns:extensions="clr-namespace:MyApp.Extensions;assembly=MyApp">
<ContentPage.Resources>
<!--Do it as part of a style-->
<Style x:Key="ButtonLayoutStyle" TargetType="StackLayout">
<Setter Property="Spacing">
<extensions:ResponsiveValue x:TypeArguments="x:Double" Default="0,54">
<extensions:ResponsiveSet Breakpoint="{x:Static extensions:Breakpoint.Small}" x:TypeArguments="x:Double">0,10</extensions:ResponsiveSet>
<extensions:ResponsiveSet Breakpoint="{x:Static extensions:Breakpoint.Medium}" x:TypeArguments="x:Double">0,54</extensions:ResponsiveSet>
<extensions:ResponsiveSet Breakpoint="{x:Static extensions:Breakpoint.Large}" x:TypeArguments="x:Double">
<OnPlatform x:TypeArguments="x:Double">
<OnPlatform.iOS>0,76</OnPlatform.iOS>
<OnPlatform.Android>0,70</OnPlatform.Android>
</OnPlatform>
</extensions:ResponsiveSet>
</extensions:ResponsiveValue>
</Setter>
<Setter Property="Margin">
<extensions:ResponsiveValue x:TypeArguments="Thickness" Default="0,170,0,0">
<extensions:ResponsiveSet Breakpoint="{x:Static extensions:Breakpoint.Small}" x:TypeArguments="Thickness">0,26,0,0</extensions:ResponsiveSet>
<extensions:ResponsiveSet Breakpoint="{x:Static extensions:Breakpoint.Medium}" x:TypeArguments="Thickness">0,16,0,0</extensions:ResponsiveSet>
<extensions:ResponsiveSet Breakpoint="{x:Static extensions:Breakpoint.Large}" x:TypeArguments="Thickness">
<OnPlatform x:TypeArguments="Thickness">
<OnPlatform.iOS>0,12,0,0</OnPlatform.iOS>
<OnPlatform.Android>0,14,6,0</OnPlatform.Android>
</OnPlatform>
</extensions:ResponsiveSet>
</extensions:ResponsiveValue>
</Setter>
<Setter Property="VerticalOptions" Value="Center" />
</Style>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout>
<!-- Do it inline -->
<StackLayout.Spacing>
<extensions:ResponsiveValue x:TypeArguments="x:Double" Default="10">
<extensions:ResponsiveSet Breakpoint="{x:Static extensions:Breakpoint.Medium}" x:TypeArguments="x:Double">5</extensions:ResponsiveSet>
<extensions:ResponsiveSet Breakpoint="{x:Static extensions:Breakpoint.Large}" x:TypeArguments="x:Double">
<OnPlatform x:TypeArguments="x:Double">
<OnPlatform.iOS>12</OnPlatform.iOS>
<OnPlatform.Android>10</OnPlatform.Android>
</OnPlatform>
</extensions:ResponsiveSet>
</extensions:ResponsiveValue>
</StackLayout.Spacing>
<StackLayout.Margin>
<extensions:ResponsiveValue x:TypeArguments="Thickness" Default="0,170,0,0">
<extensions:ResponsiveSet Breakpoint="{x:Static extensions:Breakpoint.Small}" x:TypeArguments="Thickness">0,100,0,0</extensions:ResponsiveSet>
<extensions:ResponsiveSet Breakpoint="{x:Static extensions:Breakpoint.Medium}" x:TypeArguments="Thickness">0,142,0,0</extensions:ResponsiveSet>
<extensions:ResponsiveSet Breakpoint="{x:Static extensions:Breakpoint.Large}" x:TypeArguments="Thickness">
<OnPlatform x:TypeArguments="Thickness">
<OnPlatform.iOS>0,160,0,0</OnPlatform.iOS>
<OnPlatform.Android>0,154,0,0</OnPlatform.Android>
</OnPlatform>
</extensions:ResponsiveSet>
</extensions:ResponsiveValue>
</StackLayout.Margin>
<!-- Your content here -->
</StackLayout>
</ContentPage.Content>
using System;
using System.Collections.Generic;
using System.Linq;
using Xamarin.Essentials;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace MyApp.Extensions
{
public enum Breakpoint
{
Small = 642,
Medium = 829,
Large = 1599,
}
[ContentProperty("Query")]
public class ResponsiveValue<T> : IMarkupExtension
{
public IList<ResponsiveSet<T>> Query { get; set; } = new List<ResponsiveSet<T>>();
public T Default { get; set; }
public object ProvideValue(IServiceProvider serviceProvider)
{
var size = GetSize();
foreach (var resolutions in Query.OrderBy(r => r.Breakpoint))
{
if (size > (int)resolutions.Breakpoint)
continue;
return resolutions.Value;
}
return Default;
}
public double? GetSize()
{
// Application.Current.MainPage.Width was returning -1
// so use Xamarin Essentials to get the screen width.
var mainDisplayInfo = DeviceDisplay.MainDisplayInfo;
Console.WriteLine($"Density is {mainDisplayInfo.Density}.");
return mainDisplayInfo.Width;
}
}
[ContentProperty("Value")]
public class ResponsiveSet<T>
{
public T Value { get; set; }
public Breakpoint Breakpoint { get; set; }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment