I usually find positioning content in XAML more comfortable than in CSS. However, I got stuck with an alignment problem which turned out to have an elegant solution. Let’s look at this brain teaser together!
Consider the following layout:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Grid> | |
<Button HorizontalAlignment="Stretch" MaxWidth="250">Example</Button> | |
</Grid> |
We have a stretched button which has a maximum width of 250
. The result looks like this:
What if we now wanted to align the stretched button to the left or the right?
That turns out to be quite challenging. You cannot specify a horizontal alignment like StartAndExpand
and EndAndExpand
– these options are available in Xamarin.Forms only. Applying HorizontalAlignment
in the containing Grid
changes the rules completely – it forces the Button
to have the minimum possible width it needs, so stretching no longer has the intended effect.
If you want to tackle this brain teaser yourself, take a break from reading here and try it! If you find a different solution than the one presented, please let me know in the comments!
Left alignment
We can move the MaxWidth
attribute to a ColumnDefinition
in our grid and make the single column *
(star) wide:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Grid> | |
<Grid.ColumnDefinitions> | |
<ColumnDefinition Width="*" MaxWidth="250" /> | |
</Grid.ColumnDefinitions> | |
<Button HorizontalAlignment="Stretch">Example</Button> | |
</Grid> |
The column of the Grid
is stretched but has a maximum width of 250
. Columns in Grid
start on the left-hand side, so the column is left-aligned as well but the button within it can still stretch.
Right alignment
One column is not sufficent for right-alignment, but we can use a very similar trick again with two columns:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Grid> | |
<Grid.ColumnDefinitions> | |
<ColumnDefinition Width="*" /> | |
<ColumnDefinition Width="*" MaxWidth="250" /> | |
</Grid.ColumnDefinitions> | |
<Button HorizontalAlignment="Stretch" Grid.Column="1">Example</Button> | |
</Grid> |
The button will now resides in the second column, which has the same properties as in the previous example. The new first column has *
(star) width as well and its purpose is to fill the space remaining after arranging the second column.
This sort of works. Sort of – unless the screen is narrow. In that case, the rule which states that columns of *
width evenly distribute the available width of the Grid
takes precedence and both columns have get the same width.
We need to find another way out. We must trick the Grid
into thinking the second column should be significantly wider by default:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Grid> | |
<Grid.ColumnDefinitions> | |
<ColumnDefinition Width="*" /> | |
<ColumnDefinition Width="10000*" MaxWidth="250" /> | |
</Grid.ColumnDefinitions> | |
<Button HorizontalAlignment="Stretch" Grid.Column="1">Example</Button> | |
</Grid> |
By giving the second column width of 10000*
its width, Grid
would by default make the second column 10000 times as wide as the first. Now in combination with MaxWidth
it constrains the width to exactly 250
even on narrow screen, and we get precisely the result we wanted:
In case you found a different solution for this brain teaser I would love to know! Please let me know in the comments 🙂💻 .
I have to be honest.. my immediate thought was ‘that’s not actually difficult – just use columndefinitions and split the grid containing the button up…’
But I’ve been doing XAML since it came out.. so… 🙂
Conversely, if you asked me to do something like that with CSS I’d be lost.
How about setting width of first column to Auto and second to *?
Take the left align solution, rotate the grid by 180 to the right and then rotate its content by -180 to the left.
Ha! That’s an amazing solution!
Take the left aligned solution, rotate the grid by 180 to the right and then rotate its content by -180 to the left.