Xamarin.Forms: how to center a multine label in a Row? - xaml

I try to vertically center a multiline Label that contains a text that can be displayed on 1 or 2 lines.
For the moment, I'm not able to get the expected rendering...
I can have the multiline label that automatically extends but it is top aligned and not centered:
This is the attached XAML:
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="0" />
</Grid.RowDefinitions>
<local:MultiLineLabel
Grid.Row="0"
Grid.Column="1"
BackgroundColor="Orange"
Text="{ Binding encart_titre }"
VerticalTextAlignment="Center"
LineBreakMode="TailTruncation"
Lines="2"
...
/>
I can also center the label, but in this case it doesn't auto extends:
This is the attached XAML:
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="0" />
</Grid.RowDefinitions>
<local:MultiLineLabel
Grid.Row="0"
Grid.Column="1"
BackgroundColor="Orange"
Text="{ Binding encart_titre }"
VerticalTextAlignment="Center"
LineBreakMode="TailTruncation"
Lines="2"
VerticalOptions="FillAndExpand"
...
/>
Would you have any explanation? I also tried to add StackLayound around the Label, but this didn't change anything...

The first choice for centering a control would be to use VerticalOptions="CenterAndExpand", have you tried that instead of VerticalOptions="FillAndExpand"? Here's more information about the LayoutOptions in Xamarin.Forms.
So, this would be the correct way to center vertically:
<local:MultiLineLabel
Grid.Row="0"
Grid.Column="1"
BackgroundColor="Orange"
Text="{ Binding encart_titre }"
VerticalTextAlignment="Center"
LineBreakMode="TailTruncation"
Lines="2"
VerticalOptions="CenterAndExpand" <!-- This one here -->
...
/>

Related

How to collapse a grid row in XAML?

I would like to know if it is possible to collapse a row in a grid ?
I already collapsed the controls inside my row (using Visibility = "Collapsed" + Height = "Auto").
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label Content="Test 1"/>
<ProgressBar Grid.Column="1" Value="90"/>
<Label Content="Test 2" Grid.Row="1" Visibility="Collapsed"/>
<ProgressBar Grid.Column="1" Grid.Row="1" Value="50" Visibility="Collapsed"/>
<Label Content="Test 3" Grid.Row="2"/>
<ProgressBar Grid.Column="1" Grid.Row="2" Value="20"/>
</Grid>
But I would like to collapse all the row, whitout doing it for each control in the row, like that :
<RowDefinition Height="Auto" Visibility="Collapsed"/>
Is it possible ? Or should I use something other than a grid ?
Thanks.

How to prevent Visual Studio XAML Designer from changing Grid size definitions?

I have a Grid defined in XAML like this:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition />
<RowDefinition Height="30" />
<RowDefinition Height="2*" />
<RowDefinition Height="30" />
<RowDefinition Height="4*" />
<RowDefinition Height="30" />
<RowDefinition Height="2*" />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel Grid.Row="5" />
</Grid>
If you want to modify the grid by adding/removing rows/columns, you may have to update the Grid.Row/Grid.Column attached properties for many of the grid's children (e. g. when deleting the first two rows, the StackPanel needs to be changed from Grid.Row="5" to Grid.Row="3").
This can become cumbersome if the grid has many children already. Therefore, when modifying an already populated grid at design time, I'm using the visual side of the XAML Designer, because that automatically updates the attached properties of the grid's contents accordingly.
For adding, this works perfectly fine:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition />
<RowDefinition Height="30" />
<RowDefinition Height="80" /><!-- inserted, simply adjust height as needed -->
<RowDefinition Height="2*" />
<RowDefinition Height="30" />
<RowDefinition Height="4*" />
<RowDefinition Height="30" />
<RowDefinition Height="2*" />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel Grid.Row="6" /><!-- updated -->
</Grid>
For deleting however, it also updates any RowDefinition/ColumnDefinition that has a dynamic size definition (* unit). For example, after deleting the first two rows, I'm left with something like this:
<Grid>
<Grid.RowDefinitions>
<!-- first two removed -->
<RowDefinition Height="30" />
<RowDefinition Height="59*" /><!-- was 2* -->
<RowDefinition Height="30" />
<RowDefinition Height="117*" /><!-- was 4* -->
<RowDefinition Height="30" />
<RowDefinition Height="59*" /><!-- was 2* -->
<RowDefinition Height="29*" /><!-- was implicit 1* -->
</Grid.RowDefinitions>
<StackPanel Grid.Row="3" /><!-- updated -->
</Grid>
Ideally, I want to get the following result:
<Grid>
<Grid.RowDefinitions>
<!-- first two removed, others unchanged -->
<RowDefinition Height="30" />
<RowDefinition Height="2*" />
<RowDefinition Height="30" />
<RowDefinition Height="4*" />
<RowDefinition Height="30" />
<RowDefinition Height="2*" />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel Grid.Row="3" /><!-- updated -->
</Grid>
Right now, I always have to remember to copy the definitions I want to keep before deleting rows or columns in the Visual Designer, so I can paste the copied definition over the mess that got created. But that doesn't even work unless you're only deleting at the edges.
Is there an option to tell the XAML Designer to not pseudo-optimize the size definitions?
I tried things like holding Shift or Control while clicking the "Delete row" menu item, and I looked into the (very few) XAML Designer settings that VS offers, but so far to no avail.
I have Visual Studio 2019 Professional.

Xamarin.Forms: how to position a Circle Image above and between 2 ScrollLayout

I work on a Xamarin.Forms app containing a HomePage based on:
an Image at the top background of the screen
a list of items displayed in a ScrollView
The ScrollView can recover the Image if the list contain many informations.
This looks like this:
The XAML looks like this:
<Grid RowSpacing="0"
BackgroundColor="{StaticResource Gray-050}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="1">
<!-- Header view -->
<ScrollView>
<ContentView x:Name="headerView"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- the BoxView will be replaced by an Image -->
<BoxView x:Name="headerImage"
HeightRequest="280"
BackgroundColor="Yellow" />
</Grid>
</ContentView>
</ScrollView>
<!-- List view -->
<ScrollView HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<Grid ColumnSpacing="0"
RowSpacing="0"
VerticalOptions="FillAndExpand">
<Grid.RowDefinitions>
<RowDefinition Height="140" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- Main container -->
<yummy:PancakeView CornerRadius="16,16,0,0"
Padding="0,10,0,0"
BackgroundColor="{StaticResource Gray-050}"
Grid.Row="1">
<StackLayout BackgroundColor="Transparent"
Spacing="16" Margin="16">
<!-- Phone container -->
<yummy:PancakeView Style="{StaticResource YummyHomeFrame}"
Padding="16">
<Grid RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Style="{StaticResource HomePageHeaderLabelStyle}"
Text="Phone Number" />
<Label Grid.Row="1"
Style="{StaticResource HomePageLabelStyle}"
Text="+33 6 20 10 70 40" />
</Grid>
</yummy:PancakeView>
<!-- Other containers -->
</StackLayout>
</yummy:PancakeView>
</Grid>
</Grid>
</ScrollView>
</Grid>
</Grid>
I would like to display a circle logo between the 2 ScrollViews, just above the MainContainer, something like this:
But I don't have managed to achieve this, and I don't know if it's possilbe...
You could have a try with RelativeLayout to achieve that.
Here is similar sample codeļ¼š
<ScrollView HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<Grid ColumnSpacing="0"
RowSpacing="0"
VerticalOptions="FillAndExpand">
<Grid.RowDefinitions>
<RowDefinition Height="140" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- Main container -->
<RelativeLayout>
<Frame CornerRadius="16" x:Name="MainFrame"
Padding="0,10,0,0"
BackgroundColor="LightBlue"
Grid.Row="1">
<StackLayout BackgroundColor="Transparent"
Spacing="16"
Margin="16">
<!-- Phone container -->
<Frame Padding="16">
<Grid RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Text="Phone Number" />
<Label Grid.Row="1"
Text="+33 6 20 10 70 40" />
</Grid>
</Frame>
<!-- Other containers -->
</StackLayout>
</Frame>
<BoxView CornerRadius="25"
BackgroundColor="AliceBlue"
RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToView, ElementName=MainFrame, Property=Width,Factor=0.45}"
RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToView, ElementName=MainFrame, Property=Y,Constant=-20}"
RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToView, ElementName=MainFrame, Constant=100}"
RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToView, ElementName=MainFrame, Constant=100}" />
</RelativeLayout>
</Grid>
</Grid>
</ScrollView>
The effect:
Add you circle logo at the same level of the container.
<!-- Items view -->
<ScrollView HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<Grid
ColumnSpacing="0"
RowSpacing="0"
VerticalOptions="FillAndExpand">
<Grid.RowDefinitions>
<RowDefinition Height="140" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- Container -->
<Frame ...>
<!-- Yoour logo -->
<Frame
Grid.Row="1"
Margin="0,-40,0,0"
BackgroundColor="Green"
CornerRadius="40"
HeightRequest="40"
HorizontalOptions="Center"
VerticalOptions="Start"
WidthRequest="40" />
</Grid>
</Grid>
</ScrollView>
Check the demo:
As I didn't use the nugget package, I just replaced the pancake view with a frame. And you can adjust the logo size, margin as you wish.
Btw, your structure is a bit complex or redundant, could be a 4-level main structure as below:
<Grid x:Name="mainGrid">
<!-- Header view -->
<BoxView (or Image).../>
<!-- Items view -->
<ScrollView ...>
<Grid ...>
<!-- Container -->
<Frame ...>
<!-- logo -->
<Frame (or Image)...>
</Grid>
</ScrollView>
</Grid>
Thank you #Shaw and #Junior Jiang - MSFT
There are so 2 solutions: with or without RelativeLayout.
The version without RelativeLayout was given by #Shaw.
<Grid RowSpacing="0"
BackgroundColor="LightGray"
x:Name="mainGrid">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="1">
<!-- Header view -->
<ScrollView>
<ContentView x:Name="headerView"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- the BoxView can be replaced by an Image -->
<BoxView x:Name="headerImage"
HeightRequest="280"
BackgroundColor="Yellow" />
</Grid>
</ContentView>
</ScrollView>
<!-- Content View -->
<ScrollView HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<Grid ColumnSpacing="0"
RowSpacing="0"
VerticalOptions="FillAndExpand">
<Grid.RowDefinitions>
<RowDefinition Height="140" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- Frame Container-->
<Frame x:Name="MainFrame"
CornerRadius="16"
Padding="0,10,0,0"
BackgroundColor="LightGray"
Grid.Row="1">
<StackLayout BackgroundColor="Transparent"
Spacing="16" Margin="16,48,16,16">
<!-- Phone Frame -->
<Frame Padding="16">
<Grid RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Text="Phone Number" />
<Label Grid.Row="1"
Text="+33 6 20 10 70 40" />
</Grid>
</Frame>
<!-- Other Frames -->
<!-- ... -->
</StackLayout>
</Frame>
<!-- No RelativeLayout positioned item -->
<BoxView Grid.Row="1"
CornerRadius="45"
BackgroundColor="DarkBlue"
WidthRequest="90" HeightRequest="90"
VerticalOptions="Start" HorizontalOptions="Center"
Margin="0,-45,0,0" />
</Grid>
</Grid>
</ScrollView>
</Grid>
</Grid>
The version with RelativeLayout is based on #Junior Jiang - MSFT suggestion:
<Grid RowSpacing="0"
BackgroundColor="LightGray"
x:Name="mainGrid">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="1">
<!-- Header View -->
<ScrollView>
<ContentView x:Name="headerView"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- the BoxView can be replaced by an Image -->
<BoxView x:Name="headerImage"
HeightRequest="280"
BackgroundColor="Yellow" />
</Grid>
</ContentView>
</ScrollView>
<!-- Content View -->
<ScrollView HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<Grid ColumnSpacing="0"
RowSpacing="0"
VerticalOptions="FillAndExpand">
<Grid.RowDefinitions>
<RowDefinition Height="140" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackLayout Grid.Row="1">
<RelativeLayout>
<!-- Frame container -->
<Frame x:Name="MainFrame"
CornerRadius="16"
Padding="0,10,0,0"
BackgroundColor="LightGray"
Grid.Row="1">
<StackLayout BackgroundColor="Transparent"
Spacing="16" Margin="16,48,16,16">
<!-- Phone Frame -->
<Frame Padding="16">
<Grid RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Text="Phone Number" />
<Label Grid.Row="1"
Text="+33 6 20 10 70 40" />
</Grid>
</Frame>
<!-- Other Frames -->
<!-- ... -->
</StackLayout>
</Frame>
<!-- RelativeLayout positioned item -->
<BoxView CornerRadius="45"
BackgroundColor="DarkBlue"
WidthRequest="90" HeightRequest="90"
VerticalOptions="Center" HorizontalOptions="Center"
RelativeLayout.XConstraint="{ConstraintExpression
Type=RelativeToParent,
Property=Width,
Factor=0.5,
Constant=-45}"
RelativeLayout.YConstraint="{ConstraintExpression
Type=RelativeToView,
ElementName=MainFrame,
Property=Y,Constant=-45}" />
</RelativeLayout>
</StackLayout>
</Grid>
</ScrollView>
</Grid>
</Grid>

Not let Scroll View Appear Larger when made Larger But Instead Make the Overflow Text Appear if you Scroll More, Xamarin

Here is the code I have so far in XAML
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label Grid.Row="0" Text="{Binding EquationString}" />
<Entry Grid.Row="1" x:Name="entry" Placeholder="Put Answer Here" />
<Button Grid.Row="2" x:Name="btnCheck" Text="Check Answer"/>
<Label Grid.Row="3" Text="{Binding CheckMessageString}"/>
<BoxView Grid.Row="4" Color="Black" HeightRequest="1" HorizontalOptions="FillAndExpand"/>
<Grid Grid.Row="5" BackgroundColor="White">
<skia:SKCanvasView x:Name="canvasView"
PaintSurface="OnCanvasViewPaintSurface"
BackgroundColor="White"/>
<Grid.Effects>
<tt:TouchEffect Capture="True"
TouchAction="OnTouchEffectAction" />
</Grid.Effects>
</Grid>
<BoxView Grid.Row="6" Color="Black" HeightRequest="1" HorizontalOptions="FillAndExpand"/>
<Grid Grid.Row="7">
<Button Grid.Column="0" x:Name="btnClear" Text="Clear"/>
<Button Grid.Column="1" x:Name="btnAnalyze" Text="Analyze"/>
</Grid>
<ScrollView Grid.Row="8">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label Grid.Row="0" Text="{Binding ResultString}"/>
<Label Grid.Row="1" Text= "{Binding WorkString}"/>
</Grid>
</ScrollView>
</Grid>
Here is what the view originally looks like
When I press the button Analyze the Text WorkString changes be 4 \n. However I do not want the size of the drawing canvas to change.
Instead what I want to happen is that the size of everything stays the same as before I pressed the button except that the overflow text is now scrollable. In which you have to scroll in order to see that text. Can you guys please assist me with how to do this? Thank you.
If you want fix size on scrollview ,just hard code the last height of RowDefinition, do not use Auto .
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="30"/> //this line
</Grid.RowDefinitions>

Xamarin.Forms How to put text/label over a BoxView element?

I am trying to achieve the result such as in the attached design sample below, I want to add the label SIGN UP and LOGIN over the blue and dark color BoxViews that I successfully created to match the design.
It seems that I cannot add label into a BoxView in Xamarin.Forms so I would like to please know what is a good way to achieve this result.
Currently I am overlapping the BoxViews over the middle column.
<Grid
Margin="0"
ColumnSpacing="0"
RowSpacing="0"
VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand">
<Grid.RowDefinitions>
<!--0 blank -->
<RowDefinition Height="5*" />
<!--1 logo -->
<RowDefinition Height="15*" />
<!--2 blank -->
<RowDefinition Height="5*" />
<!--3 main title-->
<RowDefinition Height="5*" />
<!--4 main title -->
<RowDefinition Height="5*" />
<!--5 main title-->
<RowDefinition Height="5*" />
<!--7 blank-->
<RowDefinition Height="15*" />
<!--8 subtitle-->
<RowDefinition Height="5*" />
<!--9 subtitle-->
<RowDefinition Height="5*" />
<!--10 blank-->
<RowDefinition Height="0*" />
<!--11 signup login bar-->
<RowDefinition Height="7*" />
<!--12 signup login bar-->
<RowDefinition Height="7*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="65*" />
<ColumnDefinition Width="5*" />
<ColumnDefinition Width="30*" />
</Grid.ColumnDefinitions>
<Image Source="homePageLogo.png"
Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="3"
HorizontalOptions="Center"
HeightRequest="120"
Aspect="AspectFit">
</Image>
<Label
Text="{Binding MainTitle}"
Grid.Row="3"
Grid.RowSpan="4"
Grid.Column="0"
Grid.ColumnSpan="3"
FontFamily="Gibson"
FontAttributes="Bold"
TextColor="White"
FontSize="50"
LineBreakMode="WordWrap"
HorizontalOptions="CenterAndExpand"
HorizontalTextAlignment="Center">
</Label>
<Label
Text="{Binding SubTitle}"
Grid.Row="8"
Grid.RowSpan="2"
Grid.Column="0"
Grid.ColumnSpan="3"
FontFamily="Poppins"
FontAttributes="Bold"
TextColor="White"
FontSize="Large"
LineBreakMode="WordWrap"
HorizontalOptions="CenterAndExpand"
HorizontalTextAlignment="Center">
</Label>
<!-- This is the boxview that should contain the LOGIN label -->
<BoxView
Grid.Row="11"
Grid.Column="1"
Grid.ColumnSpan="2"
Grid.RowSpan="2"
BackgroundColor="#2F3237">
</BoxView>
<!-- This is the boxview that should contain the SIGNUP label -->
<BoxView
Grid.Row="11"
Grid.Column="0"
Grid.ColumnSpan="2"
Grid.RowSpan="2"
BackgroundColor="#337EF3"
CornerRadius="0,15,0,15">
</BoxView>
</Grid>