Center content if text becomes bigger - xaml

i have this sample xaml:
<StackLayout Orientation="Horizontal"
HorizontalOptions="CenterAndExpand">
<StackLayout BackgroundColor="LightBlue">
<Label Text="ABC"
HorizontalTextAlignment="Center" />
<Label Text="L"
HorizontalTextAlignment="Center"></Label>
</StackLayout>
<BoxView BackgroundColor="Red" />
<StackLayout BackgroundColor="LightGreen">
<Label Text="ABC"
HorizontalTextAlignment="Center" />
<Label Text="C"
HorizontalTextAlignment="Center"></Label>
</StackLayout>
</StackLayout>
which produces this output:
But if one of the four lables becomes bigger there are not centered anymore:
My goal is the following layout, which depends on the biggest label:
I'm a beginner. So i hope somebody could help me with the correct layout.
Thanks

StackLayout really isn't the best choice here, because it occupies the size dynamically (i.e. depending on its content). What's the better approach here is to use Xamarin.Forms' Grid layout.
This way, you can have a grid with 3 columns. Then, you will set your ColumnDefinitions's width to star (*). Like you can see in the Rows and columns section, setting the column's width to star means that:
Star – leftover row height or column width is allocated proportionally (a number followed by * in XAML).
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackLayout Grid.Column="0" /> <!-- Blue StackLayout wrapper -->
<BoxView Grid.Column="1" /> <!-- Red BoxView -->
<StackLayout Grid.Column="2" /> <!-- Green StackLayout wrapper -->
</Grid>
Basically, you will have divided the whole screen width to 3 equal parts, each resulting in an 33,3(3) % of the screen. Then, you can align the elements in the container as you wish.

Related

How to separate Entry and Image using Grid within a Frame?

I'm making an Entry that has an Image on the right inside it.
The problem I have is that the text is placed behind the Image, what I want to do is that the text is cut off when it reaches the Image, separate the entry from the Image. I am using a Frame and inside it, a Grid. I have tried to put right margin to Entry but the Image is scrolling out. To do the Entry I am using the NuGet: Xamarin.Forms.Visual.Material
This is my code:
<StackLayout>
<Frame BackgroundColor="Transparent" HasShadow="False">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Entry
x:Name="entrycontrol"
BackgroundColor="{Binding Source={x:Reference ValidateView}, Path=BGColor}"
HeightRequest="60"
Visual="Material"
WidthRequest="{Binding Source={x:Reference ValidateView}, Path=Width}" />
<Image
x:Name="ImageRight"
Grid.Column="0"
Margin="0,0,5,0"
HeightRequest="25"
HorizontalOptions="End" />
</Grid>
</Frame>
</StackLayout>
The Source of the Image I establish it in the code behind.
Your main issue is that you are overlaying your Image on top of the Entry control. You need to specify a Grid.Column="1" so it uses the right hand column. A detailed explanation of how a Grid layout works can be found on Microsofts site
I would suggest that you do not need to bind the WidthRequest property for the Entry control. Plus I would swap your column definitions around. Auto means the column will grow in size, * means it will stretch to a size based on what other columns have been defined.
To summarise you want something like:
<StackLayout>
<Frame BackgroundColor="Transparent" HasShadow="False">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" /> <!-- swapped -->
<ColumnDefinition Width="Auto" /> <!-- swapped -->
</Grid.ColumnDefinitions>
<Entry x:Name="entrycontrol"
BackgroundColor="{Binding Source={x:Reference ValidateView}, Path=BGColor}"
HeightRequest="60"
Visual="Material" />
<Image x:Name="ImageRight"
Grid.Column="1"
Margin="0,0,5,0"
HeightRequest="25"
HorizontalOptions="End" />
</Grid>
</Frame>
</StackLayout>
Better yet if you have a fixed image size then you can simply set your ColumnDefinition to that size.

AbsoluteLayout with proportional height and with minimum and maximum heights

We need a banner, called bannerView in the code bellow, to shrink or expand according to the device height.
However this banner height:
cannot be smaller than 60 units
cannot be bigger than 146 units
code:
<AbsoluteLayout>
<StackLayout
Padding="0"
AbsoluteLayout.LayoutBounds="0,0,1,1"
AbsoluteLayout.LayoutFlags="SizeProportional"
HorizontalOptions="FillAndExpand">
<AbsoluteLayout
x:Name="bannerView">
<Image
AbsoluteLayout.LayoutBounds="0,0,1.05,1"
AbsoluteLayout.LayoutFlags="SizeProportional"
Aspect="AspectFill"
Source="banner.jpg">
</Image>
<Label
Margin="16,18,16,36"
AbsoluteLayout.LayoutBounds="0,1,-1,-1"
AbsoluteLayout.LayoutFlags="PositionProportional"
Text="{Binding Name}">
</Label>
<Label
Margin="16,18,16,18"
AbsoluteLayout.LayoutBounds="0,1,-1,-1"
AbsoluteLayout.LayoutFlags="PositionProportional"
Text="{Binding EmployeeId}">
</Label>
</AbsoluteLayout>
<StackLayout>
<!-- Dynamic content -->
</StackLayout>
</StackLayout>
</AbsoluteLayout>
Note: We need the outer AbsoluteLayout to add a gradient effect on the screen
Have you considered the possibility to use a FlexLayout containing the banner view element, and this one having the HeightRequest attribute binded to view model?
I used something similar as ControlTemplate to achieve a custom page's header depending on the device navigation bar height:
<FlexLayout Direction="Column" JustifyContent="Center">
<!--HEADER-->
<Grid IsVisible="{TemplateBinding BindingContext.ToolbarVisibled}" HeightRequest="{TemplateBinding BindingContext.ToolbarHeight}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".8*"/>
<ColumnDefinition Width=".2*"/>
</Grid.ColumnDefinitions>
<!--...-->
</Grid>
<!--CONTENT HERE-->
<FlexLayout Direction="Column" JustifyContent="Center">
<ContentPresenter FlexLayout.Grow="1"/>
</FlexLayout>
</FlexLayout>

Xamarin forms - unwanted extra space under TableView

I am creating my first Android app. I want to show TableView with some input fields and then a button to process the inputs.
I don't know why but there is extra space under TableView or the button is aligned to the bottom but it is opposite to the settings.
Can you help me fix it?
<StackLayout Orientation="Vertical" VerticalOptions="Start" Padding="20,15,20,0" Spacing="0">
<Label Text="This is TableView"></Label>
<TableView Intent="Settings" VerticalOptions="Start">
<TableRoot>
<TableSection>
<ViewCell>
<StackLayout Orientation="Horizontal">
<Label Text="item 1"/>
<Entry></Entry>
</StackLayout>
</ViewCell>
<ViewCell>
<StackLayout Orientation="Horizontal">
<Label Text="item 2"/>
<Entry></Entry>
</StackLayout>
</ViewCell>
</TableSection>
</TableRoot>
</TableView>
<Label Text="TableView - END"></Label>
<Button Text="My button" TextColor="DodgerBlue" VerticalOptions="Start" HorizontalOptions="Fill" Margin="40, 10, 40, 10"/>
<Frame VerticalOptions="StartAndExpand" BackgroundColor="Transparent" BorderColor="Black">
<StackLayout Orientation="Vertical">
<StackLayout Orientation="Horizontal" HorizontalOptions="Fill">
<Label Text="aaaa" HorizontalOptions="StartAndExpand"></Label>
<Label Text="value" HorizontalOptions="End"></Label>
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="aaaa"></Label>
<Label Text="value"></Label>
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="aaaa"></Label>
<Label Text="value"></Label>
</StackLayout>
</StackLayout>
</Frame>
</StackLayout>
Your best option is to define the RowHeight for each cell, and then specify the HeightRequest for the tableview. this way you can define the space it will occupy
<TableView Margin="0" Intent="Settings" HeightRequest="120" RowHeight="60" VerticalOptions="Start">
Unfortunately, this is how Xamarin.Forms TableView/ListView works. It is not expected to have anything below it. If you need something below you can either set the height of TableView manually or to put the content in the last cell, neither thing is perfect but in any case you need to look for some workaround as this is behavior by design (it would be a bit easier if you could use the ListView instead of TableView).
As you were asking what you can do besides using a TableView, of course a Grid would be possible, please see the following example:
<Grid VerticalOptions="StartAndExpand">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" /> <!-- for the label -->
<ColumnDefinition Width="*" />
<Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="1" /> <!-- For the separator, you might have to experiment with the height -->
<RowDefinition Height="*" />
<RowDefinition Height="1" />
</Grid.RowDefinitions>
<Label Text="Item 1" />
<Entry Grid.Row="0" Grid.Column="1" />
<BoxView BackgroundColor="Black"
HeightRequest="1"
Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="2" /> <!-- The separator -->
<Label Grid.Row="2" Grid.Column="0" Text="Item 2" />
<Entry Grid.Row="2" Grid.Column="1" />
<BoxView BackgroundColor="Black"
HeightRequest="1"
Grid.Row="3"
Grid.Column="0"
Grid.ColumnSpan="2" /> <!-- The separator -->
</Grid>
I am using BoxViews with a black background color and a HeightRequest of 1 for the separator. You might have to experiment with the color and the height to get the results you want. Values below 1 are possible and result in finer lines. In a real world example I've used .5.
Anyway, this makes the XAML way more cluttered. Grid-designs (while I am using them myself) tend to get quite unwieldy.
I am not sure if this what you are looking for but my understanding of the question tells me you are talking about the label Value being away from the rest.
if you check the code for this label :
<Label Text="value" HorizontalOptions="End"></Label>
the HorizontalOptions is set to "End" which is causing this changing it to start will fix your problem
Feel free to revert in case if I missed anything
Goodluck

xamarin.forms XAML CODE TO MINIMIZE DISTANCE BETWEEN Label and button

I am developing a xamarin.forms app and here as shown in the images I am getting wide vertical spacing between label field and buttons, so I need to decrease them and align them in proper order, here is the XAML code so please suggest me what changes do I need to make?
<ScrollView>
<StackLayout Padding="5">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".3*"></ColumnDefinition>
<ColumnDefinition Width=".5*"></ColumnDefinition>
<ColumnDefinition Width=".2*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
>
<Label Text="Name" Grid.Column="0" Grid.Row="4" Style="
{DynamicResource SizedLabel}" TextColor="Black"
VerticalOptions="CenterAndExpand" HorizontalOptions="StartAndExpand"
HorizontalTextAlignment="Start"/>
<Entry x:Name="name" Grid.Column="1" Grid.Row="4"
Placeholder="" WidthRequest="100" FontAttributes="None" FontSize="Small"
BackgroundColor="Transparent" VerticalOptions="CenterAndExpand"
HorizontalOptions="FillAndExpand"></Entry>
<Label x:Name="qty_lbl" Text=" Quantity"
Grid.Column="0" Grid.Row="5" Style="{DynamicResource SizedLabel}"
TextColor="Black" VerticalOptions="CenterAndExpand"
HorizontalOptions="StartAndExpand" HorizontalTextAlignment="Start"/>
**<Entry x:Name="quantity" Grid.Column="1" Grid.Row="6"
Keyboard="Numeric" Placeholder="" WidthRequest="100"
FontAttributes="None" FontSize="Small" BackgroundColor="Transparent"
VerticalOptions="CenterAndExpand" HorizontalOptions="FillAndExpand">
</Entry>
</Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".1*"></ColumnDefinition>
<ColumnDefinition Width=".1*"></ColumnDefinition>
<ColumnDefinition Width=".1*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Button x:Name="save_btn" BackgroundColor="DodgerBlue"
Grid.Column="0" Grid.Row="1" TextColor="White" Text="Next/Save"
Clicked="OnSave" BorderColor="Black"/>
<Button x:Name="cancel_btn" BackgroundColor="DodgerBlue"
Grid.Column="1" Grid.Row="1" TextColor="White" Text="Cancel"
Clicked="OnCancel" BorderColor="Black"/>
<Button x:Name="close_btn" BackgroundColor="DodgerBlue"
Grid.Column="2" Grid.Row="1" TextColor="White" Text="Close"
Clicked="OnClose" BorderColor="Black"/>
</Grid>**
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<StackLayout Orientation="Horizontal" HeightRequest="40"
HorizontalOptions="FillAndExpand" Grid.Column="0" Grid.Row="0"
BackgroundColor="LightGray">
<Label x:Name="count_label" Text="" Style="
{DynamicResource SizedLabel}" TextColor="Gray"
HorizontalTextAlignment="Start" VerticalOptions="CenterAndExpand"
HorizontalOptions="FillAndExpand"></Label>
</StackLayout>
</Grid>
</StackLayout>
</ScrollView>
</StackLayout>
To make the buttons move up what changes do I need to make?
thanks
The problem lays in the use you make of the Grid.Row attached property. In the first grid, you define 2 rows but, then, you assign to some of its children controls the property Grid.Row to 4, 5 and 6. This implicitly force the creation of additional rows, and you end up with a grid with 7 rows (because of course rows are 0 based).
When the rows aren't given an explicit height, they are given "*", which means "equally proportional", that is, all of the same size. That's alone create a lot of extra space.
Also, in the second Grid, the one with the buttons, you define it with only one row, but assign Grid.Row = "1" to all the three buttons, this way forcing the creation of a second row. Again, because you don't specify an height, the newly created row has the same size of the row containing the buttons.
To fix all this you have to:
Assign Grid.Row = "0" to the first Label and the first Entry.
Assign Grid.Row="1" to the second Label and the second Entry.
Assign Grid.Row="0" to all the three buttons.
If you instead want the labels to appear over the relative entry, then assign Grid.Row = "0" to the first Label, Grid.Row = "1" to the first Entry, Grid.Row = "2" to the second Label and Grid.Row = "3" to the second Entry.
Also, for clarity, define four Rows in the Grid, with Height="Auto" or Height="*".
To make your code more concise, please note:
0 is the default for both Grid.Row and Grid.Column, so you can get rid of such assignments;
You don't have to define a Grid.RowDefinitions property if your Grid has only one row. The same, you don't have to define a Grid.ColumnDefinitions property if your Grid has only one column.
There is no use in using decimal notation when expressing height or width with "*" values. Star values indicate a proportion between rows (or columns), so for example if a row is "2*" and a second row is "*", the first row will be twice as tall than the second. The sum of the stars assigned to the rows (or the columns) can be any number, because it has no particular meaning, what is important is only the relative proportions between rows (or columns). To clarify even more, in the example made before, you could have assigned "100*" to the first row and "50* to the second: the result would have been the same.

How to adjust scroll height of Xaml StackLayout?

I have a StackLayout which has items dynamically added to it when a user is selected. I want it to have a height of around 200, then if the list is longer than this, it should be scrollable.
If I add a height request to it as it is now, it adjusts the height and the scrollbar works but prevents items being added after the bottom of the box (so the scrollbar is basically pointless.
This is the code, the StackLayout is called 'readout':
<?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="Clocker.MainPage" >
<StackLayout x:Name="mainstack">
<Picker x:Name="locationpicker" SelectedIndexChanged="locationpicker_SelectedIndexChanged" BackgroundColor="#baf4d5"></Picker>
<Label x:Name="timeLabel" FontSize="50" HorizontalTextAlignment="Center" VerticalTextAlignment="Start" TextColor="White" BackgroundColor="#59a092"/>
<ScrollView Orientation="Vertical" BackgroundColor="#baf4d5">
<StackLayout x:Name="readOut">
</StackLayout>
</ScrollView>
<ListView x:Name="userslist" BackgroundColor="#59a092">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.ContextActions>
<MenuItem Clicked="OnIn" CommandParameter="{Binding .}"
Text="In" />
<MenuItem Clicked="OnOut" CommandParameter="{Binding .}"
Text="Out" IsDestructive="True" />
</ViewCell.ContextActions>
<StackLayout Padding="15,0">
<Label x:Name="lblname" Text="{Binding FullName}" TextColor="White" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
I've 2 or 3 pages in my app that are more or less like what you described.
My solution uses and 2 lists.
More or less like this:
<Grid ColumnSpacing="0" RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="2*" />
<RowDefinition Height="8*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
Row 1 is where I have my first list, row 2 is where the second list goes.
I do it this way (0 is a header and 3 is a footer), so I have more or less 20% of the left space on top and the rest of the space allocated for the second list.
Hope it's clear.