Search code examples
xamlxamarin.formsgridlabel

Xamarin forms: label horizontal arrangement


I have this view:

<?xml version="1.0" encoding="UTF-8" ?>
<ContentPage
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:xct="http://xamarin.com/schemas/2020/toolkit"
    xmlns:vm="clr-namespace:EGrid18.ViewModels"
    xmlns:gauge="clr-namespace:Syncfusion.SfGauge.XForms;assembly=Syncfusion.SfGauge.XForms"
    xmlns:managers="clr-namespace:EGrid18.Managers"
    xmlns:iOS="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
    iOS:Page.UseSafeArea="True"
    x:Class="EGrid18.Views.MainBikeInfo"
    Title="Bike Info">
    <ContentPage.Resources>
        <ResourceDictionary>
            <vm:MainBikeInfoVM x:Key="vm"/>
        </ResourceDictionary>
    </ContentPage.Resources>
    <ContentPage.Content>
        <StackLayout Margin="8" BindingContext="{Binding Source={StaticResource vm}}">
            <Frame HasShadow="False"
                   BorderColor="LightGray">
                <StackLayout Orientation="Horizontal" HorizontalOptions="Start">
                    <gauge:SfCircularGauge WidthRequest="100"
                                            HeightRequest="100">
                        <gauge:SfCircularGauge.Scales>
                            <gauge:Scale ShowLabels="False"                                          
                                          StartValue="0"
                                          EndValue="100"
                                          Interval="10"
                                          StartAngle="180"
                                          SweepAngle="180"
                                          RimThickness="10"
                                          RimColor="Gray">
                                <gauge:Scale.Ranges >
                                    <gauge:Range StartValue="0" EndValue="24" Color="Red" Thickness="4" Offset="1"/>
                                    <gauge:Range StartValue="25" EndValue="49" Color="Yellow" Thickness="4" Offset="1"/>
                                    <gauge:Range StartValue="50" EndValue="74" Color="Blue" Thickness="4" Offset="1"/>
                                    <gauge:Range StartValue="75" EndValue="100" Color="Green" Thickness="4" Offset="1"/>
                                </gauge:Scale.Ranges>
                                <gauge:Scale.Pointers>
                                    <gauge:NeedlePointer Value="{Binding BatteryLevel}"/>
                                </gauge:Scale.Pointers>
                                <gauge:Scale.MajorTickSettings>
                                    <gauge:TickSettings Length="4"
                                                         Color="Black"
                                                         Thickness="1"
                                                         Offset="1"/>
                                </gauge:Scale.MajorTickSettings>
                            </gauge:Scale>
                        </gauge:SfCircularGauge.Scales>
                        <gauge:SfCircularGauge.Headers>
                            <gauge:Header Text="F" TextSize="10" ForegroundColor="Gray" Position="0.9,0.5"/>
                            <gauge:Header Text="E" TextSize="10" ForegroundColor="Gray" Position="0.1,0.5"/>
                            <gauge:Header Text="Batt level" ForegroundColor="Black" TextSize="20"/>
                        </gauge:SfCircularGauge.Headers>
                    </gauge:SfCircularGauge>
                    <StackLayout HorizontalOptions="StartAndExpand" VerticalOptions="CenterAndExpand">
                        <Grid HorizontalOptions="Start">
                            <Label Text="Model:" FontSize="16"
                               HorizontalTextAlignment="End"
                               WidthRequest="70"
                               Grid.Column="0" Grid.Row="0"/>
                            <Label Text="Serial:"
                               FontSize="16"
                               HorizontalTextAlignment="End"
                               WidthRequest="70"
                               Grid.Column="0" Grid.Row="1"/>
                            <Label Text="Year:"
                               FontSize="16"
                               HorizontalTextAlignment="End"
                               WidthRequest="70"
                               Grid.Column="0"  Grid.Row="2"/>
                            <Label Text="{Binding BikeModelName}"
                               FontSize="14"
                               HorizontalTextAlignment="Start"
                               Grid.Column="1"  Grid.Row="0"/>
                            <Label Text="{Binding SerialNumber}"
                               FontSize="14"
                               HorizontalTextAlignment="Start"
                               Grid.Column="1" Grid.Row="1"/>
                            <Label Text="{Binding YearBuild}"
                               FontSize="14"
                               HorizontalTextAlignment="Start"
                               Grid.Column="1"  Grid.Row="2"/>
                        </Grid>
                    </StackLayout>
                </StackLayout>
            </Frame>
            <Frame HasShadow="False"
                  ... unrelated stuff                
            </Frame>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

when the view initialise all look the way I want it to be:

enter image description here

the circular Gauge is on the left and centered, and the text is on its right right next to it with proper spacing. all description labels are right aligned and all value labels are left aligned and all the unused space on the right of content.

Problem is that if I update the value labels, all the text gets shifted to the right of the frame leaving a big ugly gap between the labels and the gauge. enter image description here

Initially I used stack-layout to get the description label stack vertically in one stack then an other for the values all wrapped in a horizontal stack-layout

<StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand" Padding="8" Margin="8">
<Gauge> ... </Gauge>
<StackLayout>
  ... description labels set as End 
</StackLayout>
<StackLayout>
  ... description value labels set as StartAndExpand
</StackLayout>
</StackLayout>

but was getting the same problem and the description where not aligned the way I needed. The grid is better but I am still having this problem with the empty space getting in between the gauge and the text block


Solution

  • Simple solution. I needed to add a ColumnDefinitions to get the Grid to set the Column width to the desired width. width can have a hard value like 55 or 'auto' and '*'. Auto will let the column take as much space as it needs and the * will let the column take as much space as it can.

    https://learn.microsoft.com/en-us/dotnet/api/xamarin.forms.columndefinition?view=xamarin-forms

    ...
    </gauge:SfCircularGauge>
        <StackLayout HorizontalOptions="StartAndExpand" VerticalOptions="CenterAndExpand">
            <Grid HorizontalOptions="Start">                            
               <Grid.ColumnDefinitions>
                   <ColumnDefinition Width="Auto" /> <-- this will get the column take the space it needs
                   <ColumnDefinition Width="*" /> <-- this will have the column take all the space that it can
               </Grid.ColumnDefinitions>
               <Label Text="Model:" FontSize="16"
                      HorizontalTextAlignment="End"
                      WidthRequest="70"
                      Grid.Column="0" Grid.Row="0"/>
    ...