Xamarin stacking text below an image - xaml

I am trying to figure out how to center the image and text and push the text "Cache 3" directly below the image without the bottom red space. This stacklayout is in a collection so the images are of different heights hence I can't set a HeightRequest per se.
This is my XAML:
<StackLayout>
<Frame
Margin="10"
Padding="0"
BorderColor="{StaticResource Gray-500}"
CornerRadius="5"
HasShadow="False"
HorizontalOptions="Center"
VerticalOptions="FillAndExpand">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="3*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image
Grid.Row="0"
Margin="15"
Aspect="AspectFit"
BackgroundColor="Red"
Source="{Binding Image, Converter={StaticResource BytesToImageSource}}" />
<Label
Grid.Row="1"
Padding="15,0,15,15"
FontSize="18"
HorizontalTextAlignment="Center"
Text="{Binding Data}"
TextColor="{StaticResource Gray-900}"
VerticalTextAlignment="Center" />
</Grid>
</Frame>
</StackLayout>

Related

Xamarin iOS - How to get StackLayout to auto size to nested contents?

I have the following XAML :
<StackLayout>
<Grid IsVisible="{Binding isVisible}" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<behaviors:Expander x:Name="MainExpander" CollapseAnimationLength="500" IsExpanded="false" >
<behaviors:Expander.Header>
<Grid HorizontalOptions="FillAndExpand">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="10"/>
</Grid.ColumnDefinitions>
<Frame HeightRequest="40" WidthRequest="40" CornerRadius="20" HorizontalOptions="Start" VerticalOptions="Center" Margin="20" Padding="0" BackgroundColor="Maroon">
<Label Text="{Binding student_initial}" TextColor="White" HorizontalOptions="Center" VerticalOptions="Center" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" />
</Frame>
<StackLayout Grid.Column="2" HorizontalOptions="StartAndExpand" VerticalOptions="Center" Margin="20">
<Label x:Name="StudentName" Text="{Binding student_fullname}"></Label>
<Label x:Name="StudentID" IsVisible="false" Text="{Binding student_unique_id}"></Label>
</StackLayout>
</Grid>
</behaviors:Expander.Header>
<Grid RowSpacing="0" HorizontalOptions="FillAndExpand" HeightRequest="240" VerticalOptions="FillAndExpand">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button Grid.Row="0" Text="Messages" Clicked="Button_Clicked"></Button>
<Button x:Name="btnTopUp" Grid.Row="1" Text="Quick Topup" Clicked="Button_Clicked" IsVisible="{Binding topup_product_id, Converter={StaticResource IsNotNullOrEmptyConverter}}"></Button>
<Button Grid.Row="2" Text="Payments" Clicked="Button_Clicked"></Button>
</Grid>
<!--TODO: Look at adding a balance for childrens topups?-->
</behaviors:Expander>
</Grid>
</StackLayout>
I am trying to hide and show the grid as follows :
<Grid IsVisible="{Binding isVisible}" ...
The issue is that nothing shows as it looks like the StackLayout is unable to work out how high it needs to be. I can't explicitly set the height property as it depends if the expander is expanded or not. Is there a way to make the stack layout height auto size ? Thank you.
Replace StackLayout with Grid , set its HorizontalOptions and VerticalOptions as Start .
<Grid BackgroundColor="Red" HorizontalOptions="Start" VerticalOptions="Start">
<Grid IsVisible="false" ...
See the following screen shot in all of the scenarios (red color represents the root Grid)
Gird invisible
Grid visible (none-expanded)
Grid visible (expanded)

UI looks cropped in initial load for ios using xamarin.forms

<ListView>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ContentView Padding="6,2,6,2">
<Frame BackgroundColor="White" CornerRadius="5" Margin="10,5" HasShadow="False" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
</Frame><Grid HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label Grid.Row="0" Text="Item1" />
<Label Grid.Row="1" Text="Item2" />
<Label Grid.Row="2" Text="Item3" />
</Grid>
</ContentView>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
While with the initial load of the page UI looks like 3rd label is cropped and if I revisits the page the 3rd label showing correctly.how to show the UI perfectly with the initial load itself.issue is only occuring in ios.
From shared code, I have tested in local site on iOS. However, there is no problem in iOS device.
In addition, there is problems about this Xaml code. The Frame layout not contains the Grid , the running effect as follows:
If I put it inside will show as follows:
I also tested in Android device, however it cropped the third lable. If want to make it shows fully, we can add RowHeight for ListView, as follows:
<ListView x:Name="listview" RowHeight="125">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ContentView Padding="6,2,6,2" BackgroundColor="AliceBlue">
<Frame BackgroundColor="White"
CornerRadius="5"
Margin="10,5"
HasShadow="False"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<Grid HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label Grid.Row="0"
Text="Item1" />
<Label Grid.Row="1"
Text="Item2" />
<Label Grid.Row="2"
Text="Item3" />
</Grid>
</Frame>
</ContentView>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
The effect:

Collapse Labels and ListViews in Xamarin Forms

I've got a relatively simple view which looks something like this:
{Label1}
{Label2}
{ListView1}
{Label3}
{ListView2}
The Label2 and ListView1's IsVisible properties are binded to a bool property. When false, they don't appear however, they take up space on the UI meaning there's a considerable gap between Label1 and Label3 like this:
{Label1}
{Label3}
{ListView2}
How can I make them appear like this instead:
{Label1}
{Label3}
{ListView2}
My XAML code looks like this:
<AbsoluteLayout
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<Grid
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
AbsoluteLayout.LayoutFlags="All"
AbsoluteLayout.LayoutBounds="0,0,1,1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label
Text="Title"
HorizontalOptions="Center"
VerticalOptions="Center"
TextColor="White"
FontSize="Large"
FontAttributes="Bold"
Margin="5"
BindingContext="{x:Reference DashboardPageView}"
IsVisible="{Binding DisplayFloatingTitle}"
Grid.Row="0" />
<Label
Text="Notifications"
HorizontalOptions="Start"
VerticalOptions="Center"
TextColor="White"
FontSize="Medium"
FontAttributes="Bold"
Margin="3"
IsVisible="{Binding HasNotifications}"
Grid.Row="1" />
<ListView Grid.Row="2"
ItemsSource="{Binding Notifications}"
HasUnevenRows="True"
VerticalOptions="Start"
IsVisible="{Binding HasNotifications}"
SeparatorVisibility="None" Margin="1,0"
x:Name="NotificationsList">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
........
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Label
Text="Activities"
HorizontalOptions="Start"
VerticalOptions="Start"
TextColor="White"
FontSize="Medium"
FontAttributes="Bold"
Margin="3"
IsVisible="{Binding HasActivities}"
Grid.Row="3" />
<ListView Grid.Row="4"
ItemsSource="{Binding Activities}"
HasUnevenRows="True"
VerticalOptions="Start"
SeparatorVisibility="None" Margin="4,0"
x:Name="ActivitiesList">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
....
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</AbsoluteLayout>
The problem is this line in your XAML:
<RowDefinition Height="*" />
It's set to *, which means it will take up all remaining space that it can get. If you want the content of this row to size automatically to it's content's size, you should use Auto:
<RowDefinition Height="Auto" />

How can I overlay a Card View or a Framed layout on top of another layout in Xamarin Forms?

I have a situation where I need to "overlay" a grouped set of information, presented by way of a Card (inplemented as a ContentView) on top of a portion of the page header, which is defined in a Grid inside of a FlexLayout. The output should resemble something like the following where the header is the portion in red:
The code for the header is as follows:
<!-- Header -->
<FlexLayout
HeightRequest="108"
AlignItems="Center"
Direction="Column"
BackgroundColor="#D92732">
<Grid VerticalOptions="Center" Margin="0, 30, 0, 0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20"></ColumnDefinition>
<ColumnDefinition Width="40*"></ColumnDefinition>
<ColumnDefinition Width="80*"></ColumnDefinition>
<ColumnDefinition Width="300*"></ColumnDefinition>
<ColumnDefinition Width="80*"></ColumnDefinition>
<ColumnDefinition Width="40*"></ColumnDefinition>
<ColumnDefinition Width="20"></ColumnDefinition>
</Grid.ColumnDefinitions>
<ImageButton Source="Bell.png" Grid.Column="1" BackgroundColor="Transparent"
WidthRequest="37"
HeightRequest="40"
Aspect="AspectFit">
</ImageButton>
<Label
Grid.Column="3"
Text="Payments"
TextColor="#F9F8FA"
FontSize="20"
HeightRequest="40"
HorizontalOptions="Center"
VerticalOptions="Center" VerticalTextAlignment="End">
</Label>
<ImageButton Source="Bell.png" Grid.Column="5" BackgroundColor="Transparent"
WidthRequest="37"
HeightRequest="40"
Aspect="AspectFit">
</ImageButton>
</Grid>
</FlexLayout>
The method I used to solve the problem of having a visual element overlay a portion of another visual element, in this case a Grid overlay a portion of another Grid, is to set the position of the overlay Grid to a specific row and column of the first Grid and then set the Bottom value of the overlay Grid's Margin to a negative number that represents the desired height of the overlay Grid, as seen in the following code and screenshot. Note that I enclosed the overlaid Grid in a Frame which is where I set the negative Bottom Margin value.
<Frame Grid.Row="2" Grid.ColumnSpan="3" Grid.Column="0"
Margin="16,30,16,-310" WidthRequest="343" HeightRequest="300">
<StackLayout HeightRequest="350">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="44*" />
<RowDefinition Height="38*" />
<RowDefinition Height="40*" />
<RowDefinition Height="20*" />
<RowDefinition Height="96*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0"
FontFamily="{StaticResource HNMedium}"
FontSize="{StaticResource Font20}"
HorizontalOptions="Start"
Text="Verify Account"
TextColor="{StaticResource NGIC_DarkGray}"
VerticalOptions="Start" />
<Label Grid.Row="1"
Text="Enter the verification code sent to ******8998"
FontSize="{StaticResource Font16}"
TextColor="{StaticResource NGIC_DarkGrayishBlue}"
FontFamily="{StaticResource HNRegular}"/>
<Entry Grid.Row="2" TextColor="Black" />
<Label Grid.Row="3"
Text="Send a new code"
TextColor="{StaticResource NGIC_Red}"
FontSize="{StaticResource Font14}"
FontFamily="{StaticResource HNMedium}"/>
<StackLayout Grid.Row="4" >
<Button Text="Next"
TextColor="{StaticResource White}"
BackgroundColor="{StaticResource NGIC_Red}"
CornerRadius="15"
WidthRequest="300"
HeightRequest="40"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand"
FontFamily="{StaticResource HNBold}"
FontSize="{StaticResource Font14}"/>
<Button Text="Cancel"
TextColor="{StaticResource NGIC_Red}"
BackgroundColor="{StaticResource White}"
CornerRadius="15"
WidthRequest="300"
HeightRequest="40"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand"
FontFamily="{StaticResource HNRegular}"
FontSize="{StaticResource Font14}"
BorderColor="{StaticResource NGIC_Red}"
BorderWidth="1"/>
</StackLayout>
</Grid>
</StackLayout>
</Frame>

Xamarin margins are different between two resolutions (devices)

I have a page in xamarin with a couple of frames, all with an image (color) and text. However, i'm facing the problem that the margins of the images (colors) look different on different phones (resolutions). As you can see on the image below, the images are in the right position on the Galaxy S8 (resolution 1440x2960) and at the wrong position on the Galaxy S10e (resolution 1080 x 2280).
I am using the following code for the frames:
<Grid ColumnSpacing="12.5" RowSpacing="12.5" Padding="10" HeightRequest="500">
<Grid.RowDefinitions>
<RowDefinition Height="0.8*" />
<RowDefinition Height="4.5*" />
<RowDefinition Height="1.5*" />
<RowDefinition Height="1.5*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Frame x:Name="frame_Sport" Grid.Row="2" Grid.Column="0" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" >
<Frame.GestureRecognizers>
<TapGestureRecognizer Tapped="Sport_Clicked"/>
</Frame.GestureRecognizers>
<StackLayout Orientation="Vertical" HorizontalOptions="FillAndExpand">
<StackLayout Orientation="Horizontal" >
<Label Text=" Sport" FontSize="18"/>
</StackLayout>
<StackLayout Orientation="Vertical" >
<Label x:Name="txt_Sport" FontSize="18"/>
</StackLayout>
<Image Source="mark_green.png" Scale="0.17" Margin="-110,-137,0,0"/>
</StackLayout>
</Frame>
<Frame x:Name="frame_Voeding" Grid.Row="2" Grid.RowSpan="2" Grid.Column="1" >
<Frame.GestureRecognizers>
<TapGestureRecognizer Tapped="Voeding_Clicked"/>
</Frame.GestureRecognizers>
<StackLayout Orientation="Vertical" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" >
<Label Text=" Voeding" FontSize="18" />
<Label x:Name="txt_Voeding1" FontSize="18" Margin="0,-0.6"/>
<Label x:Name="txt_Voeding2" FontSize="18" Margin="0,-0.6"/>
<Label x:Name="txt_Voeding3" FontSize="18" Margin="0,-0.6"/>
<Label x:Name="txt_Voeding4" FontSize="18" Margin="0,-0.6"/>
<Label x:Name="txt_Voeding5" FontSize="18" Margin="0,-0.6"/>
<Label x:Name="txt_Voeding6" FontSize="18" Margin="0,-0.6"/>
<Image Source="mark_red.png" Scale="0.17" Margin="-110,-280,0,0"/>
</StackLayout>
</Frame>
<Frame x:Name="frame_Slaap" Grid.Row="3" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" >
<Frame.GestureRecognizers>
<TapGestureRecognizer Tapped="Slaap_Clicked"/>
</Frame.GestureRecognizers>
<StackLayout Orientation="Vertical" HorizontalOptions="FillAndExpand">
<StackLayout Orientation="Horizontal" >
<Label Text=" Slaap" FontSize="18" />
</StackLayout>
<StackLayout Orientation="Vertical">
<Label x:Name="txt_Slaap" FontSize="18" />
</StackLayout>
<Image Source="mark_blue.png" Scale="0.17" Margin="-110,-137,0,0"/>
</StackLayout>
</Frame>
</Grid>
Why are the images (colors) looking different on both phones, how do I fix this?
The values for Margin are in absolute units (pixels).
The Frame which contains the StackLayout has a different absolute width on every device. Therefore your positioning of the icon will differ if the resolution or dpi differs.
In your case I would create a Horizontal Stacklayout with the Image and the label like that:
<StackLayout Orientation="Vertical" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" >
<StackLayout Orientation="Horizontal">
<Image Source="mark_red.png" Scale="0.17"/>
<Label Text="Voeding" FontSize="18" />
</StackLayout>
<Label x:Name="txt_Voeding1" FontSize="18" Margin="0,-0.6"/>
...
</StackLayout>
I have a page in xamarin with a couple of frames, all with an image (color) and text. However, I'm facing the problem that the margins of the images (colors) look different on different phones (resolutions). As you can see on the image below, the images are in the right position on the Galaxy S8 (resolution 1440x2960) and at the wrong position on the Galaxy S10e (resolution 1080 x 2280).
The reason this is happening is that different devices have a different density. When it comes to Margin it is a double value and Xamarin Forms converts this double values into platform specific types (for eg Dp's, Points) respectively. Hence every device responds to the same margin in a different way based on its own size and density.
In the same way, density also affects the colour. The human perception for colour changes if the device has a denser pixels even though it is the same color but it looks a little different to us! Basically, The denser the pixels are in your device the more vivid the colour is to the naked eye.
Now coming back to the issue the reason your Margin is looking different is the same reason I explained above, Now to overcome this issue you might want to either remove the StackLayout use Grid instead and define a proper Column definition in a way that they align properly.
<Grid>
<Grid.ColumnDefinitions> <--<Define these as they suit you>-->
.
.
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="mark_red.png" Scale="0.17"/>
<Label Grid.Column="1" Text="Voeding" FontSize="18" />
</Grid>
Or Increase the Spacing property of the StackLayout so it adds a little extra space between the Image and the Label:
<StackLayout Orientation="Horizontal" Spacing="10"> <--<Default spacing is 6>-->
<Image Source="mark_red.png" Scale="0.17"/>
<Label Text="Voeding" FontSize="18" />
</StackLayout>
Update:
Your XAML should look like this:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="mark_red.png" Scale="0.17"/>
<Label Grid.Column="1" Text="Voeding" FontSize="18" />
<StackLayout Grid.Row="1" Grid.ColumnSpan="2" >
<Label x:Name="txt_Voeding1" FontSize="18" Margin="0,-3"/>
<Label x:Name="txt_Voeding2" FontSize="18" Margin="0,-3"/>
<Label x:Name="txt_Voeding3" FontSize="18" Margin="0,-3"/>
<Label x:Name="txt_Voeding4" FontSize="18" Margin="0,-3"/>
<Label x:Name="txt_Voeding5" FontSize="18" Margin="0,-3"/>
<Label x:Name="txt_Voeding6" FontSize="18" Margin="0,-3"/>
</StackLayout>
</Grid>