Xamarin Forms: Expand Button size in a Grid for larger Accessible Text - xamarin

I am creating a search form with an Entry and a Button at the top. I have it all laid out well when the text is a normal size. I have implemented scaling fonts for accessibility, and now when the font is at the second to largest size the font is too big for the button and it cuts off the text.
Here is my current code. I don't require using a grid, it's just the only way I could get the entry control to fill out all of the extra space that the button isn't using. The width and height requests on the controls is the only way I could get them to look well on normal text sizing
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<controls:BorderedEntry Grid.Column="0" x:Name="queryEntry" Text="{Binding QueryString}" FontSize="{DynamicResource StandardLabelFontSize}"
BorderColor="{AppThemeBinding Light={StaticResource PrimaryColorLight}, Dark={StaticResource PrimaryColorDark}}" CompletedCommand="{Binding FindTextCommand}"
Placeholder="Search string" ReturnType="Search" ClearButtonVisibility="WhileEditing"
VerticalOptions="CenterAndExpand" HeightRequest="{OnPlatform Android=50, iOS=35}" Margin="10,15,5,5"
IsClippedToBounds="True" CornerRadius="5" AutomationId="TextSearchEntry" />
<Button Grid.Column="1" Text="Find" Command="{Binding FindTextCommand}" Margin="0,10,10,0" WidthRequest="80"
HeightRequest="35" IsEnabled="{Binding QueryString, Converter={StaticResource NonEmptyStringValue}}"
FontSize="{DynamicResource StandardLabelFontSize}" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand"/>
</Grid>
Here is what it looks like on normal text sizing:
Here is what it looks like on the third to largest text size:
Here is what happens once I go to the second to, and largest text size:
And here is ideally what I would like it to look like at a minimum visual. I got this by setting the buttons width request to 100 instead of 80 (I ideally don't want this value as it doesn't look good on small text size):
The only solution I have came up with is keep track of what the text scaling is, and once it goes above 1.5, then I can increase the WidthRequest on the button control. Ideally I would just like the button to adjust to the width of the text.
EDIT 1:
I tried Jason's solution with this code here:
<StackLayout Orientation="Horizontal">
<controls:BorderedEntry Text="{Binding QueryString}" FontSize="{DynamicResource StandardLabelFontSize}"
BorderColor="{AppThemeBinding Light={StaticResource PrimaryColorLight}, Dark={StaticResource PrimaryColorDark}}" CompletedCommand="{Binding FindTextCommand}"
Placeholder="Search string" ReturnType="Search" ClearButtonVisibility="WhileEditing"
VerticalOptions="CenterAndExpand" HeightRequest="{OnPlatform Android=50, iOS=40}" Margin="10,15,5,5"
HorizontalOptions="FillAndExpand"
IsClippedToBounds="True" CornerRadius="5" AutomationId="TextSearchEntry" />
<Button Text="Find" Command="{Binding FindTextCommand}" Margin="0,10,10,0"
IsEnabled="{Binding QueryString, Converter={StaticResource NonEmptyStringValue}}"
FontSize="{DynamicResource StandardLabelFontSize}" VerticalOptions="Center"
Padding="20,0,20,0"/>
</StackLayout>
I had to leave the HeightRequest on the Entry else the entry would be a smaller height. Without the Padding on the Button it showed like so:
Adding the padding added some space to the button (I tried this instead of the WidthRequest):
So now it looks good on normal text, however once I start cranking up the text size in accessibility, it looks good on the 3rd to largest size (same as my original solution above):
But once I move it to the top two it starts pushing the button off the screen to the right:
Then I had the idea to go back to using the Grid and using Padding instead of the WidthRequest on the Button, and it displays correctly:

this works for me. As I change the FontSize of the button, the entry will adjust to accomodate
<StackLayout Padding="10,100,10,0" HeightRequest="50" Orientation="Horizontal" BackgroundColor="LightBlue">
<Entry HorizontalOptions="FillAndExpand" Placeholder="Search" />
<Button FontSize="80" Text="Find" />
</StackLayout>

After trying out Jason's suggested solution it still did not layout properly at the largest text accessibility settings (see my edits above in the original post). I tried putting a Padding="20,0,20,0" on the Button and removed the WidthRequest to add spacing around the Find text in the normal text size case and that seems to have allowed the Grid to auto-layout the width I also removed the HeightRequests on both controls. I don't like how the Find button looks as it is larger than the entry. Here's the final xaml:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<controls:BorderedEntry Grid.Column="0" Text="{Binding QueryString}" FontSize="{DynamicResource StandardLabelFontSize}"
BorderColor="{AppThemeBinding Light={StaticResource PrimaryColorLight}, Dark={StaticResource PrimaryColorDark}}" CompletedCommand="{Binding FindTextCommand}"
Placeholder="Search string" ReturnType="Search" ClearButtonVisibility="WhileEditing"
VerticalOptions="CenterAndExpand" Margin="10,15,5,5"
IsClippedToBounds="True" CornerRadius="5" AutomationId="TextSearchEntry" />
<Button Grid.Column="1" Text="Find" Command="{Binding FindTextCommand}" Margin="0,10,10,0"
IsEnabled="{Binding QueryString, Converter={StaticResource NonEmptyStringValue}}"
FontSize="{DynamicResource StandardLabelFontSize}" VerticalOptions="CenterAndExpand"
Padding="20,0,20,0"/>
</Grid>
With these visuals on normal text (iOS / Android):
And these visuals on the largest text size (iOS / Android):
To fix the issue where the Find button is taller than I really want it to be on the normal text, I added conditional Binding depending on what the font scaling is:
private void SetButtonBinding()
{
if (App.Current.CurrentFontScale < ScaleFontThreshold)
{
findButton.SetBinding(Button.HeightRequestProperty, nameof(FindViewModel.ButtonHeightRequest));
}
else
{
findButton.RemoveBinding(Button.HeightRequestProperty);
}
}
Which achieves these final visuals:
I wish there was a way to do this all through Xaml, but I can't seem to find the settings.

Related

How can I move the relative position of an image in a grid?

I am creating a car app that lists cars and their prices, model, speed, etc. I wanted to position the price over an image of the car, like so:
To do this, I created a grid and allowed the image to fill the entire thing while forcing the text (with a frame around it) into a lower column/row. However, I am ending up with white space on the top of the graph. Take a look. I set the grid to a background color of blue for easier viewing.
The issue here is the aspect ratio, because an image that did fill the entire grid would cut off the sides. The size of the whitespace is equivalent to the overlay, so if I had the overlay any lower that would result in more whitespace on both sides.
Note: Some of the cars have different aspect ratios, so this has to be a fix that would work for other images as well.
Note 2: This has to be a relative position fix, since obvious methods like setting the image's margin to -100 wouldn't work on other resolution screens and would probably get me fired.
The question: How can I relatively (e.g. make it work on every screen) force the image to the top of the page while still keeping the same aspect ratio and keeping the overlay?
Here's the front-end.
<StackLayout>
<!-- Image and cost grid-->
<Grid BackgroundColor="Blue">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="63*"/>
<ColumnDefinition Width="35*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="75*"/>
<RowDefinition Height="25*"/>
</Grid.RowDefinitions>
<Image Source="{Binding ImageLocation}" Grid.ColumnSpan="3" Grid.RowSpan="2"/>
<Frame BackgroundColor="White" CornerRadius="5" Grid.Column="1" Grid.Row="1">
<Label Text="{Binding Cost}" FontSize="Large" HorizontalTextAlignment="End" TextColor="Black"/>
</Frame>
</Grid>
<!-- Information about the car -->
<StackLayout Padding="15">
<Label Text="{Binding Company}" FontSize="Large"/>
<Label Text="{Binding Model}" FontSize="Medium" FontAttributes="Bold"/>
</StackLayout>
</StackLayout>
Move your frame not the image.
Set Grid content in one row.
Set Frame VerticalOptions to End
Set Frame HeightRequest and Margin (minus value).
Set bottom StackLayout VerticalOptions to FillAndExpand
<StackLayout>
<!-- Image and cost grid-->
<Grid BackgroundColor="Blue" ColumnDefinitions="63*, 35*, 2*">
<Image Source="{Binding ImageLocation}" Grid.ColumnSpan="3"/>
<!-- Shape the Frame here -->
<Frame HeightRequest="40" Margin="0,0,0,-20" VerticalOptions="End"
BackgroundColor="White" CornerRadius="5" Grid.Column="1" >
<Label Text="{Binding Cost}" FontSize="Large" HorizontalTextAlignment="End" TextColor="Black"/>
</Frame>
</Grid>
<!-- Information about the car -->
<StackLayout Padding="15" VerticalOptions="FillAndExpand">
<Label Text="{Binding Company}" FontSize="Large"/>
<Label Text="{Binding Model}" FontSize="Medium" FontAttributes="Bold"/>
</StackLayout>
</StackLayout>

resize image in xamarin without wrapping it in stacklayout

I have a lottie animation that is disabled after it is clicked again.
This is what my lottie animation looks like:
Paused:
Played:
As we can see the actual "Image" size is bigger. My row definition size is "Auto", and HeightRequest="180", WidthRequest="180" for the lottie animation.
What I want to happen here is if the lottie animation is disabled, my image that is overlapped with the animation will be (IsVisible) true.
But even if my HeightRequest="10" and WidthRequest="10" the image looks like this:
How can I achieve it to look like the size of the first image without wrapping it with stacklayout? I dont want to wrap it with stacklayout because I want my UI to be responsive.
If I use this code:
<StackLayout Grid.Row="2"
Grid.ColumnSpan="2"
Padding="0,55,0,0">
<Image Source="red_record"
HeightRequest="85"
WidthRequest="85"
x:Name="red_record_lottie"
IsVisible="True"
/>
</StackLayout>
It will look like the desired output (for the UI):
But we know that the code will not make it responsive. How can I make it responsive?
try using a frame since the image is circular u can have a frame and change the corner radius to make a circle.
https://montemagno.com/xamarin-forms-how-to-clip-images-with-rounded-corners/
this might help u and further explain my point of view
According to your description, you just want to get the desire image size, I suggest you can use Grid and Frame to get it.The CornerRadius property of the Frame control can be used to create a circle image.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Frame
Margin="10"
BorderColor="Black"
CornerRadius="50"
HorizontalOptions="Center"
IsClippedToBounds="True"
VerticalOptions="Center">
<Image
Margin="-20"
Aspect="AspectFill"
HeightRequest="100"
Source="a11.jpg"
WidthRequest="100" />
</Frame>
</Grid>
You can also just use Frame to circle image, to set Frame's HeightRequest and WidthRequest
<Frame
Margin="10"
BorderColor="Black"
CornerRadius="50"
HeightRequest="60"
HorizontalOptions="Center"
IsClippedToBounds="True"
VerticalOptions="Center"
WidthRequest="60">
<Image
Margin="-20"
Aspect="AspectFill"
HeightRequest="100"
Source="a11.jpg"
WidthRequest="100" />
</Frame>
Well... as ironic as it may sound, I have found a solution just now... and I wrapped it with stacklayout 😅😅
This is the code that worked for me:
<StackLayout Grid.Row="2"
Grid.ColumnSpan="2"
Padding="0,0,0,0">
<forms:AnimationView x:Name="blue_record_lottie"
Animation="blue_record.json"
Loop="True"
AutoPlay="False"
HeightRequest="180"
WidthRequest="180"
Margin="0,10,0,10"
OnClick="blue_record_lottie_OnClick"/>
<Image Source="dark_red_rec"
HeightRequest="85"
WidthRequest="85"
Margin="0,55,0,60"
x:Name="red_record_lottie"
IsVisible="False"/>
</StackLayout>
I am also surprised and I have proven this by testing on my emulator (Pixel Pie 2: 1080x1920), and my physical device (samsung galaxy core: 480 x 800).
On my Pixel Pie:
On my Samsung Galaxy Core:

Adding labels on both ends of a progress bar in Xamarin Forms

I have a progress bar in Xamarin Forms defined in my XAML.
Actually I want to add labels beneath the progress that shows the minimum and maximum value of the progress bar as shown in the image below:
My XAML code:
<StackLayout Orientation="Vertical" Margin="5">
<Frame Padding="10"
BackgroundColor="White"
HeightRequest="80">
<Frame.Content>
<Label Text="%" HorizontalTextAlignment="End" FontSize="Small"/>
<ProgressBar x:Name="myProgressBar" WidthRequest="100"
HeightRequest="15" VerticalOptions="Center" HorizontalOptions="Center" Progress="0.2"/>
</Frame.Content>
</Frame>
</StackLayout>
Can someone please help me to achieve this in Xamarin Forms ? Also, how can I add a gradient color like in the image ?
For the text, you would probably want to use labels positioned under the progressbar. I'd recommend a grid with two rows.
As for the gradient, unfortunately the xamarin forms progress bar doesn't support this out of the box. You can either create a custom renderer for each platform that draws the gradient, or consider a third party control like Syncfusion's (https://www.syncfusion.com/products/xamarin/progress-bar)
You can make a custom Xamarin Forms control.
The content could be something like that:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5* />
<ColumnDefinition Width="0.5* />
</Grid.ColumnDefinition>
<Image x:Name="gradientImage" Grid.Row="0" Grid.ColumnSpan="2" Margin="10,10,10,0" />
<Frame x:Name="progressFrame" Grid.Row="0" Width="{Binding Progress}" HorizontalOption="End" BackgroundColor="Gray" ... />
<!-- Labels -->
<Label x:Name="startLbl" Grid.Row="1" Grid.Column="0" Text="{Binding startLabel}" HorizontalOption="Start" />
<Label x:Name="endLbl" Grid.Row="1" Grid.Column="1" Text="{Binding endLabel}" HorizontalOption="End" />
</Grid>
For the gradient progress bar, instead of CustomRenderers you can use an image.
this image will be the full width gradient bar
over this image, like a MASK, there is a frame. You have to compute the frame width depending on the progress value. ==> It will 'make appear" the gradient image smotthly when progress will increase.
Hope you understand the concept :)
Then in the code behind (in your ViewModel ?) manage the start/end label values and the computation of the "progress" value... I presume you will have to make a Binding Converter for: "progress" ==> "bar Width"...
Tell me if it's clear
Wanted to comment on above answer from #KFactory but don't have permission yet.
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5* />
<ColumnDefinition Width="0.5* />
</Grid.ColumnDefinition>
Has a few typos. missing end quotes and s on closing tag. Should be
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*" />
<ColumnDefinition Width="0.5*" />
</Grid.ColumnDefinitions>

How to use an Image on multiple rows in a Grid properly in Xamarin Forms

I am trying to create a custom, material-style, card cell in my Xamarin Forms app. I have the appearance pretty much down, but I'm having problems with the image in it. I want it to touch the top and bottom edges, the left hand edge, and be a square sort of shape, while maintaining the aspect ratio. But right now, all I get is this small image that won't play ball:
(I've had to cover the company images with paint, but trust me that they're about that size).
Here's what I actually want (again, please excuse the paint job)
I'm using an image in a grid view, in the 1st column and spanning all 4 rows. I've tried all of the LayoutOptions, which I used to understand but now I'm second guessing myself. I've also tried putting the image in a StackLayout as I thought you can expand children of a Stacklayout, but still no dice. Here is my simplified Xaml right now:
<Frame CornerRadius="10"
Margin="10, 5"
IsClippedToBounds="True"
BackgroundColor="White">
<Grid BackgroundColor="White" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackLayout Grid.Row="0" Grid.Column="0" Grid.RowSpan="4"
HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<Image HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Aspect="AspectFill" Source="{Binding ImageSource}"/>
</StackLayout>
<Label Grid.Row="0" Grid.Column="1"
Text="{Binding Favourite.FavKindName}"
FontSize="{DynamicResource InfoLargerTextFontSize}"/>
<Image Grid.Row="1" Grid.Column="3" Grid.RowSpan="4" Source="Contact.png"
VerticalOptions="CenterAndExpand" >
<Image.GestureRecognizers>
<TapGestureRecognizer />
</Image.GestureRecognizers>
</Image>
</Grid>
</Frame>
What's more, you can probably tell I'm pretty clueless about the phone icon on the right. I want that to occupy the centre and be of a decent button size for the card cell.
I've spent hours trying to figure this out. What am I doing wrong?
Frame has a default Padding of 20. That's why you have those margins inside the frame.
<Frame Padding="0" // Here , set padding to 0, so you can fill all Frame space
CornerRadius="10"
Margin="10, 5"
IsClippedToBounds="True"
BackgroundColor="White">

Xamarin.Forms: is possible to create a Button containing both a Text and and an icon fonts as Image?

I tried to create a button that looks like this:
But, I would like to use a icon fonts (like FontAwesome) instead of a Bitmap as source of the Image.
I thought that I could it with Iconize, but it's not the case: IconizeButton only replace the Text by the FontIcon.
So is there a way to manage both label in Text and FontIcon in Image for a Button?
I did this workaround
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="36"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition ></ColumnDefinition>
<ColumnDefinition Width="1"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button Text="Sign in" Clicked="LoginHandle_Tapped" FontAttributes="Bold" FontFamily="SFUIDisplay" FontSize="14" BorderRadius="18" HeightRequest="36" BorderWidth="0" TextColor="White" Grid.Column="0" BackgroundColor="#FF0067"/>
<Label Text="navigate_next" FontFamily="Material Icons" FontSize="16" FontAttributes="None" TextColor="#FFFFFFFF" HeightRequest="36" Margin="-30,10,0,0" Grid.Column="1"/>
</Grid>
This works for me - purple icon to the left of white button text - all inside the button.
<Button Margin="0,10,0,0" StyleClass="Button" Text="ABC"
Command="{Binding OpenWebCommand}"
TextColor="White">
<Button.ImageSource>
<FontImageSource FontFamily="FontAwesomeRegular"
Color="Purple"
Glyph="{x:Static helpers:FontAwesomeIcons.ThumbsUp}"/>
</Button.ImageSource>
</Button>
I think you can create a View with a Grid (1 row and 2 columns).
In column 1 you add the Iconize control (with a tapgesture). In Column 2 you add a Label (with a tapGesture). It should works

Resources