Setting RelativeLayout ConstraintExpressions from XAML Styles in Xamarin Forms…

When it comes to Xamarin Forms RelativeLayout we always use Constraints, its pretty easy to add those Constraint values from C# code behind, but when it comes to XAML UI implementation, it’s not so easy.

so myself…

I have been working with XAML UI implementation for the last year or so, specially dealing with a lot of pixel perfect design, which needs a lot of customization to design from XAML. But as a developer you have to find ways to deal with those stuff. In my current project we practice a strict discipline of MVVM pattern, which we strongly separate XAML UI View and the ViewModel code. So under no exceptions we add any single C# UI code or XAML code behind implementations in our project.

complex design implementations…

When you have to deal with complex design implementations in Xamarin Forms, the best way to go is with RelativeLayout, along with Relative Constraint values for X/Y position and Height/Width values.

flag1

RelativeLayout is good…

Usually those RelativeLayout Constraint values manages to get the job done, with ease on both Android and iOS devices. But sometimes it doesn’t quite go right, specially with Android, where you have to deal with different types of screen resolutions.

layouts1

but sometimes…

So at times like that you need to specify RelativeLayout ConstraintExpression separately for iOS and Android devices. But how do you do this in XAML code?

so how?

So how do you set those ConstraintExpression right from XAML code? Styles is the answer! 😀

The trick is to create two different Styles for Android and iOS, targeting the control you need to set the RelativeLayout Constraints on.

And then on your control’s XAML declaration, you set the Style property using the OnPlatform tag accordingly for iOS and Android.

Let’s do it…

You could define these Styles on your Page level or Application level as you wish as shown below…

You can see I have created twp styles which targets the Label control type and added my Relative Layout ConstraintExpressions. 🙂 Also I have added the other Properties that I need to customize through these Styles.

<ContentPage.Resources>
	<ResourceDictionary>
		<Style x:Key="MyLabelStyleiOS" TargetType="Label">
		  <Setter Property="BackgroundColor" Value="Yellow"/>
		  <Setter Property="HorizontalTextAlignment" Value="Center"/>
		  <Setter Property="RelativeLayout.YConstraint" 
				  Value="{ConstraintExpression RelativeToParent,Property=Height,Factor=0.5}"/>
		  <Setter Property="RelativeLayout.WidthConstraint"
				  Value="{ConstraintExpression RelativeToParent,Property=Width,Factor=0.7}"/>
		  <Setter Property="RelativeLayout.XConstraint"
				  Value="{ConstraintExpression RelativeToParent,Property=Width,Factor=0.15}"/>
		</Style>

		<Style x:Key="MyLabelStyleAndroid" TargetType="Label">     
		  <Setter Property="BackgroundColor" Value="Yellow"/>
		  <Setter Property="HorizontalTextAlignment" Value="Center"/>
		  <Setter Property="RelativeLayout.YConstraint"
				  Value="{ConstraintExpression RelativeToParent,Property=Height,Factor=0.1}"/>
		  <Setter Property="RelativeLayout.WidthConstraint"
				  Value="{ConstraintExpression RelativeToParent,Property=Width,Factor=0.7}"/>
		  <Setter Property="RelativeLayout.XConstraint"
				  Value="{ConstraintExpression RelativeToParent,Property=Width,Factor=0.15}"/>
		</Style>
	</ResourceDictionary>
</ContentPage.Resources>

 

And then on the your Control that you need to set those RelativeLayout Constraints…

<Label Text="Welcome to the app!"  >
	<Label.Style>
	  <OnPlatform x:TypeArguments="Style"
				  iOS="{StaticResource MyLabelStyleiOS}"
				  Android="{StaticResource MyLabelStyleAndroid}" />
	</Label.Style>
</Label>

 

You can see how I have nested down the Style property and added the specific style according to the Platform type.

It’s very important to notice that I have added those Styles as StaticResource this is because we need to set those RelativeLayout ConstraintExpressions before the run time, while the XAML are being parsed. 🙂 Once the XAML layout is parsed, we can not set the ConstraintExpressions, since it’s not going to be rendered.

make it pretty… Generalize!

Yep the above styles are ugly, so let’s generalize it and move the common properties and constraints to a general style as below, and derive our child styles.

<Style x:Key="MyLabelStyle" TargetType="Label">
  <Setter Property="BackgroundColor" Value="Yellow"/>
  <Setter Property="HorizontalTextAlignment" Value="Center"/>
  <Setter Property="RelativeLayout.WidthConstraint"
		  Value="{ConstraintExpression RelativeToParent,Property=Width,Factor=0.7}"/>
  <Setter Property="RelativeLayout.XConstraint"
		  Value="{ConstraintExpression RelativeToParent,Property=Width,Factor=0.15}"/>
</Style>

<Style x:Key="MyLabelStyleiOS" TargetType="Label" BasedOn="{StaticResource MyLabelStyle}">
  <Setter Property="RelativeLayout.YConstraint" 
		  Value="{ConstraintExpression RelativeToParent,Property=Height,Factor=0.5}"/>
</Style>

<Style x:Key="MyLabelStyleAndroid" TargetType="Label" BasedOn="{StaticResource MyLabelStyle}">
  <Setter Property="RelativeLayout.YConstraint"
		  Value="{ConstraintExpression RelativeToParent,Property=Height,Factor=0.1}"/>
</Style>

 

There we go! now that’s beautiful. Always keep in mind to generalize the common Style properties, and here in this case the common ConstraintExpression values. 🙂

Cheers! 😀

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s