Flexlayout or grid for better screen sizes handling - xamarin.forms

Xamarin layout advice
Hi given the nature of mobile devices screen sizes as a rule of thumb when building screen
would you say use "Flexlayout" all the time rather than a grid.
It is my understanding that the flexlayout is more suitable for adapting to various screens sizes without building complexity in your pages.
Still do not understand "Grow and shrink" despite reading few documentations.
How would you describe grow and shrink?
Sample one
<Grid
RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="3*" />
<RowDefinition Height="6*" />
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<StackLayout Grid.Row="0" BackgroundColor="Green">
<Label Text="Header with logo"
HorizontalTextAlignment="Center"
VerticalTextAlignment="Center" />
</StackLayout>
<StackLayout Grid.Row="1" BackgroundColor="LightBlue">
<Label Text="Content"
HorizontalTextAlignment="Center"
VerticalTextAlignment="Center" />
</StackLayout>
<StackLayout Grid.Row="2" BackgroundColor="Red">
<Label Text="Footer"
HorizontalTextAlignment="Center"
VerticalTextAlignment="Center" />
</StackLayout>
</Grid>
VS
<FlexLayout Direction="Column">
<!-- Header -->
<Label Text="HEADER"
FontSize="Large"
BackgroundColor="Aqua"
HorizontalTextAlignment="Center" />
<!-- Body -->
<FlexLayout FlexLayout.Grow="1">
<!-- Content -->
<Label Text="Content"
FontSize="Large"
BackgroundColor="Gray"
HorizontalTextAlignment="Center"
VerticalTextAlignment="Center"
FlexLayout.Grow="1" />
</FlexLayout>
<!-- Footer -->
<Label Text="FOOTER"
FontSize="Large"
BackgroundColor="Pink"
HorizontalTextAlignment="Center" />
</FlexLayout>

Grow setting of 1. This means that all the extra vertical space is allocated to this blank Label like these screenshot.
I add second label called content2, if I set grow 0, content2 will not fill extra vertical space
if I set grow 1, content2 will fill extra vertical space
shrink property plays a role when the Wrap property is set to NoWrap and the aggregate width of a row of children is greater than the width of the FlexLayout, or the aggregate height of a single column of children is greater than the height of the FlexLayout. Normally the FlexLayout will display these children by constricting their sizes. The Shrink property can indicate which children are given priority in being displayed at their full sizes.
You can download this demo, and test it by yourself.
https://developer.xamarin.com/samples/xamarin-forms/UserInterface/FlexLayoutDemos/

Related

Xamarin's forms Date Picker android icon a bit out of way

I am trying to place a synfcusion button that has a calendar image near a xarmain forms entry box.
But its a bit out of alignment what I have tried so far is.
<Label Text="Please select a start date below"></Label>
<StackLayout Orientation="Horizontal">
<Entry x:Name="txtDateStartEntry" WidthRequest="200" ></Entry>
<syncfusion:SfButton x:Name="btnPickStartDate" CornerRadius="10" HorizontalTextAlignment="Start" ShowIcon="True" Clicked="btnPickStartDate_Clicked" FontSize="24" BorderThickness="2" TextColor="White" BackgroundColor="White" Text="..." >
<syncfusion:SfButton.Content>
<Grid ColumnDefinitions="Auto, *, Auto" ColumnSpacing="16" Padding="16">
<Image Grid.Column="1" HorizontalOptions="End" WidthRequest="30" HeightRequest="30" Source="cal16.png" VerticalOptions="End"/>
</Grid>
</syncfusion:SfButton.Content>
</syncfusion:SfButton>
</StackLayout>
What I have eneded up with is this.
As you can see its a bit far away from the entry field and doesnt look like it belongs.
If you're using Syncfusion, you should make use of SfTextInputLayout which provides leading/trailing view functionality for the express purpose of adding descriptive iconography to an input view.
Code example assumes importing the following xmlns:
xmlns:sftl="clr-namespace:Syncfusion.XForms.TextInputLayout;assembly=Syncfusion.Core.XForms"
<sftl:SfTextInputLayout TrailingViewPosition="Inside">
<Entry x:Name="txtDateStartEntry" WidthRequest="200" />
<sftl:SfTextInputLayout.TrailingView>
<Image HeightRequest="30" Source="cal16.png">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="btnPickStartDate_Clicked" />
</Image.GestureRecognizers>
</Image>
<sftl:SfTextInputLayout.TrailingView>
</sftl:SfTextInputLayout>
Note: when using LeadingView or TrailingView, it's recommended to not assign a Width value as Syncfusion will calculate the width based on the height you request to maintain aspect ratio of the specified view. Therefore I have intentionally excluded HeightRequest from the Image.

Xamarin Forms CarouselView and ScrollView already scrolled without visited

I have a CarouselView with inside a ScrollView .
I've seen it plastered across documentation that it's not advisable to nest a scrollview inside any other scrollable layout, but what else can I do when I need to be able to scroll between items and each item must have scrollable content also.
Now my problem is with iOS (with all version after 10+) and Android (will all version after 6+). Let's assume we have 10 items and during the first display I make a vertical scroll in the middle of the content. When I get to the fifth view it is not displayed as a new element and therefore from the top but in the middle. If I do it to the second, the sixth mirrors the second and so on. In practice it seems that the views are linked by 5 in 5.
Here is my simple code:
<CarouselView ItemsSource="{Binding Monkeys}"
HorizontalScrollBarVisibility="Never" >
<CarouselView.ItemTemplate>
<DataTemplate>
<StackLayout Orientation="Vertical" Spacing="0">
<ScrollView VerticalScrollBarVisibility="Never" HorizontalScrollBarVisibility="Never" >
<StackLayout>
<Image
Source="{Binding ImageUrl}" HeightRequest="350"
Aspect="AspectFill" />
<Label Text="{Binding Name}"
LineBreakMode="TailTruncation"/>
<Label Text="{Binding Details}" FontSize="35" />
<Label Text="{Binding Details}" FontSize="35" TextColor="Aqua"/>
<Label Text="{Binding Details}" FontSize="35" TextColor="Fuchsia"/>
<Label Text="{Binding Details}" FontSize="35" TextColor="OliveDrab"/>
</StackLayout>
</ScrollView>
<Label Text="Fixed Button" BackgroundColor="Red" TextColor="White" HeightRequest="50" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" />
</StackLayout>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
GIF dimostration

Xamarin Forms Horizontal / Vertical options don' seem to be working

I have the following XAML in my Xamarin Forms project
<StackLayout x:Name="slFullPage" Orientation="Vertical" HorizontalOptions="Fill" VerticalOptions="FillAndExpand" Margin="0,0,0,0" BackgroundColor="AliceBlue">
<localapp:PageHeader x:Name="pgHeader" VerticalOptions="Start" HorizontalOptions="Fill" />
<combobox:SfComboBox x:Name="cmbLanguage" DataSource="{Binding LangaugesByAppLanguage}" TextSize="Micro"
TextColor="#283655" SelectionChanged="cmbLanguage_SelectionChanged"
Watermark="{localapp:Translate SelectValue}" DropDownItemHeight="25" WidthRequest="250" HeightRequest="30"
DropDownTextSize="Micro" BackgroundColor="White" HorizontalOptions="Center" VerticalOptions="Start"
DisplayMemberPath="LanguageName" SelectedValuePath="ISO_639_1_Code">
</combobox:SfComboBox>
<StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand" VerticalOptions="End" BackgroundColor="Aqua">
<buttons:SfButton x:Name="btnCancel" Text="{localapp:Translate Cancel}" HorizontalOptions="Start" VerticalOptions="End" Margin="8,0,4,0"/>
<buttons:SfButton x:Name="btnDone" Text="{localapp:Translate Done}" HorizontalOptions="End" VerticalOptions="End" Margin="4,0,8,0"/>
</StackLayout>
<localapp:AppFooter x:Name="pgFooter" VerticalOptions="End" HorizontalOptions="Fill" />
</StackLayout>
Based on my understanding of the horizontal options that can be specified on an object, I would expect the Cancel button to be at the start of my horizontal stack layout and my Done button to be at the end of the same stack layout.
Additionally, based on the vertical options that can be used, I would expect the stacklayout with the buttons in it as well as my appfoot to appear at the bottom of my slFullPage stack layout. However, neither of those things are happening.
Instead what I get can be seen below:
You can see that the entire page stacklayout is going all the way to the bottom of the screen but my buttons and footer are not at the bottom.
Additinally, you can see the horizontal stack layout (aqua) goes all the way across the screen but the buttons are not positioned based on their horizontal options.
Any ideas?? FYI - I am running the project as a UWP app.
Based on my understanding of the horizontal options that can be specified on an object, I would expect the Cancel button to be at the start of my horizontal stack layout and my Done button to be at the end of the same stack layout.
You could use a AbsoluteLayout to make the buttons positioned anywhere within a view.
<AbsoluteLayout BackgroundColor="LightBlue" HeightRequest="60" VerticalOptions="EndAndExpand">
<Button Text="Cancel" Margin="10,10" BackgroundColor="DarkBlue" TextColor="White"/>
<Button Text="Done" Margin="10,10" AbsoluteLayout.LayoutBounds="1, 0, AutoSize, AutoSize" AbsoluteLayout.LayoutFlags="PositionProportional" BackgroundColor="DarkBlue" TextColor="White"/>
</AbsoluteLayout>
And use the VerticalOptions="EndAndExpand" to make it appears at the end of its parent and expands.
Updated:
I do not know what it was before, but for now, it doesn’t actually fill up the space in the StackLayout. It’s only when the fill option is used, that it will expand to that space.
When you expect the Cancel button to be at the start and the Done button to be at the end of the same stack layout, fill option and expend need to be setted. I use simple example to display.
<StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand" VerticalOptions="EndAndExpand" BackgroundColor="Aqua">
<Button x:Name="btnCancel" Text="Cancel" HorizontalOptions="StartAndExpand" Margin="8,0,4,0"/>
<Button x:Name="btnDone" Text="Done" HorizontalOptions="EndAndExpand" Margin="4,0,8,0"/>
</StackLayout>
And if you do not want space between last two lines in the end, you need a nested stacklayout to do that without space.
Simple code:
<StackLayout BackgroundColor="LightGray">
<StackLayout>
<Entry x:Name="pgHeader" Text="pgHeader" HorizontalOptions="FillAndExpand" />
<Entry x:Name="cmbLanguage" Text="cmbLanguage" WidthRequest="250" HeightRequest="30"
BackgroundColor="Red" HorizontalOptions="CenterAndExpand" ></Entry>
</StackLayout>
<StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="EndAndExpand">
<StackLayout Orientation="Horizontal" BackgroundColor="Aqua">
<Button x:Name="btnCancel" Text="Cancel" HorizontalOptions="StartAndExpand" Margin="8,0,4,0"/>
<Button x:Name="btnDone" Text="Done" HorizontalOptions="EndAndExpand" Margin="4,0,8,0"/>
</StackLayout>
<Entry x:Name="pgFooter" Text="pgFooter"/>
</StackLayout>
</StackLayout>
You don't want to use a StackLayout (well 2 StackLayout), but a Grid:
It's more convenient for your layout, and it is way more performant.
<Grid ColumnSpacing="0" RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="40" />
<RowDefinition Height="40" />
</Grid.RowDefinitions>
<Grid.ColumnDefinition>
<ColumnDefinition Width="80" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="80" />
</Grid.ColumnDefinition>
<localapp:PageHeader Grid.Row="0" x:Name="pgHeader" />
<combobox:SfComboBox Grid.Row="1" x:Name="cmbLanguage" DataSource="{Binding LangaugesByAppLanguage}" TextSize="Micro"
TextColor="#283655" SelectionChanged="cmbLanguage_SelectionChanged"
Watermark="{localapp:Translate SelectValue}" DropDownItemHeight="25" WidthRequest="250"
DropDownTextSize="Micro" BackgroundColor="White" HorizontalOptions="Center"
DisplayMemberPath="LanguageName" SelectedValuePath="ISO_639_1_Code">
</combobox:SfComboBox>
<buttons:SfButton Grid.Row="2" Grid.Column="0"
x:Name="btnCancel" Text="{localapp:Translate Cancel}" Margin="8,0,4,0"/>
<buttons:SfButton Grid.Row="2" Grid.Column="2"
x:Name="btnDone" Text="{localapp:Translate Done}" Margin="4,0,8,0"/>
</Grid>

xamarin grid always wrong size

I have no idea what I'm doing wrong here. I've tried explicitly setting heights, column definitions, but I cannot get the sizing here to be correct.
I tried setting two columns with one row, with and without explicit heights and sizes.
What do I have to do?
something like this should work
<ViewCell>
<!-- need to specify an overall height -->
<Grid HeightRequest="200">
<Grid.RowDefinitions>
<!-- two rows equal height -->
<RowDefinition Height="50*" />
<RowDefinition Height="50*" />
</Grid.RowDefinitions>
<Grid.ColumnDefintions>
<!-- two cols equal width -->
<ColumnDefintions Width="50*" />
<ColumnDefintions Width="50*" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Text="Location" />
<Label Grid.Row="0" Grid.Column="1" Text="Amount" />
<Label Grid.Row="1" Grid.ColumnSpan="2" Text="Created" />
</Grid>
</ViewCell>

Xamarin.Forms - How to position an element on top of another element?

I have an image slider and I want to position a search box on top of the image slider.
Here is my code:
<StackLayout HeightRequest="200" >
<cv:CarouselView Margin="0" ItemsSource="{Binding Zoos}" x:Name="CarouselZoos">
<cv:CarouselView.ItemTemplate>
<DataTemplate>
<Image Grid.RowSpan="1" Grid.Row="0" Aspect="AspectFill" Source="{Binding ImageUrl}"/>
</DataTemplate>
</cv:CarouselView.ItemTemplate>
</cv:CarouselView>
</StackLayout>
<StackLayout>
<SearchBar FontAttributes="Bold"
FontFamily="Raleway.ttf#Raleway"
FontSize="11"
Placeholder="SEARCH FOR MEDICINE AND PRODUCTS"
HorizontalOptions="Center" VerticalOptions="CenterAndExpand"
Focused="SearchBar_Focused"/>
</StackLayout>
The easiest way to do this is to wrap your element into a grid and placing the second one into the same grid.
The grid layout will put all elements inside the same cell over each other with the last one being added laying topmost.
<Grid>
<Image ... />
<Label VerticalOptions="Center" HorizontalOptions="Center" />
</Grid>
This example would put the label in the mid over the image.
When using interactive elements, keep in mind that they have to be the last ones added in order to be clickable.
So for instance, if you had
<Grid>
<Button ... />
<Image ... />
</Grid>
the button would end up being overlayed by the image and therefore not be clickable.

Resources