Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Force a view to be square in shape

I am trying to create a UI in XAML for Xamarin Forms in which I have a frame (though I assume the answer would be the same for any type of view) inside of a grid. I want the frame to use full width available to it in the grid cell that it occupies, but I want to force it to be square in shape. So, I want the width to size automatically, and have the height set to match its actual width.

Here's what I have so far:

  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="*"/>
      <RowDefinition Height="*"/>
      <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="2*"/>
      <ColumnDefinition Width="6*"/>
      <ColumnDefinition Width="*"/>
      <ColumnDefinition Width="13*"/>
      <ColumnDefinition Width="2*"/>
    </Grid.ColumnDefinitions>

    <Button Grid.Row="0" Grid.Column="1"/>
    <Button Grid.Row="1" Grid.Column="1"/>
    <Button Grid.Row="2" Grid.Column="1"/>
    <Frame Grid.Row="0" Grid.Column="3" Grid.RowSpan="3" OutlineColor="Silver" HorizontalOptions="Fill">
      <Image />
    </Frame>
  </Grid>

Currently, the frame correctly fills the available width, but the height is about the same as the total height of the 3 buttons to the left of it combined.

I was thinking that I maybe needed to bind the frame's HeightRequest to its actual width, but I don't know if that's possible, or how to do it if it is. If not, any other options?

like image 757
JoeMjr2 Avatar asked May 03 '16 05:05

JoeMjr2


1 Answers

Since you're setting the RowSpan of the frame to 3, even if you explicitly set the frame's HeightRequest to some small value, the frame will still take up the entire grid's height. So first you have to prevent that from happening. You could do that by containing the frame inside some other view.

Now to make the frame's height and width the same as it scales, you could use the container's SizeChanged event and set the frame's height and width requests accordingly.

Also note that Frame by default has a padding of 20.

Here's the sample code for the xaml:

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="2*"/>
            <ColumnDefinition Width="6*"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="13*"/>
            <ColumnDefinition Width="2*"/>
        </Grid.ColumnDefinitions>

        <Button Grid.Row="0" Grid.Column="1"/>
        <Button Grid.Row="1" Grid.Column="1"/>
        <Button Grid.Row="2" Grid.Column="1"/>

        <StackLayout x:Name="frmContainer" Grid.Row="0" Grid.Column="3" Grid.RowSpan="3" BackgroundColor="Orange">
            <Frame x:Name="frm" OutlineColor="Silver" VerticalOptions="Center" HorizontalOptions="Center" Padding="0" BackgroundColor="Green"/>
        </StackLayout>
    </Grid>

And here's the constructor in the code-behind:

    InitializeComponent();

    frmContainer.SizeChanged += (s, e) =>
    {
        frm.HeightRequest = frmContainer.Width;

        if (frmContainer.Width > frmContainer.Height)
        {
            frm.WidthRequest = frmContainer.Height;
        }
        else
        {
            frm.WidthRequest = frmContainer.Width;
        }
    };
like image 143
chaosifier Avatar answered Nov 07 '22 19:11

chaosifier