Entry texts not align (- and numbers) - xamarin

Im trying to build email code validator. Im sending 6 digit number to customer to enter his code on entry.
But - and numbers has different width which cause when user enter the number then i replace - to number but it moving different alignment.I need to set them same line. How can i do it?
First one empty box, second one numbers and space, third one is how supposed to look.

This is the perfect example of using Xamarin.Forms Grid layout
If you check out the Usage section, you will see what will happen if you decide to have proportional sizes:
Proportional() – sizes columns and rows as a proportion of the remaining space. Specified as a value and GridUnitType.Star in C# and as # in XAML, with # being your desired value. Specifying one row/column with * will cause it to fill the available space.
What this means is that if you want to have 6 equal columns, you can do it like so:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
</Grid>
This way, each column will be equal to the rest and will be exactly 1/6 of the size that the grid has occupied.
You can simply place your controls inside the grid, align them accordingly and you are good to go.
P.S. If you have some special symbols, or a mixture of numbers & letters, they still may not be perfectly aligned and you will have to use a font with Fixed-pitch

I solved it with set HorizontalTextAlignment to center.
<Grid HorizontalOptions="CenterAndExpand" ColumnSpacing="0" WidthRequest="205">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Entry Placeholder="—" HorizontalOptions="Center" HorizontalTextAlignment="Center" Grid.Column="0"
Keyboard="Numeric" MaxLength="1" TextChanged="Entry_TextChanged"></Entry>
<Entry Placeholder="—" HorizontalOptions="Center" HorizontalTextAlignment="Center" Grid.Column="1"
Keyboard="Numeric" MaxLength="1" TextChanged="Entry_TextChanged"></Entry>
<Entry Placeholder="—" HorizontalOptions="Center" HorizontalTextAlignment="Center" Grid.Column="2"
Keyboard="Numeric" MaxLength="1" TextChanged="Entry_TextChanged"></Entry>
<Entry Placeholder="—" HorizontalOptions="Center" HorizontalTextAlignment="Center" Grid.Column="3"
Keyboard="Numeric" MaxLength="1" TextChanged="Entry_TextChanged"></Entry>
<Entry Placeholder="—" HorizontalOptions="Center" HorizontalTextAlignment="Center" Grid.Column="4"
Keyboard="Numeric" MaxLength="1" TextChanged="Entry_TextChanged"></Entry>
<Entry Placeholder="—" HorizontalOptions="Center" HorizontalTextAlignment="Center" Grid.Column="5"
Keyboard="Numeric" MaxLength="1"></Entry>
</Grid>
And add this C# code for when value entered focus on next entry.
private void Entry_TextChanged(object sender, TextChangedEventArgs e)
{
var entry = sender as Entry;
var list = (entry.Parent as Grid).Children;
var index = list.IndexOf(entry);
int nextIndex = 0;
if (e.NewTextValue.Length > 0)
nextIndex = (index + 1) >= list.Count ? 0 : index + 1;
else if (e.NewTextValue.Length < 1 && index > 0)
nextIndex = (index - 1);
var next = list.ElementAt(nextIndex);
next?.Focus();
}

It would be helpful to see your code, but i'm going to take a stab at it. Use FormattedText and have each item (either - or number) as a span.
<Label InputTransparent="True">
<Label.FormattedText>
<FormattedString>
<Span Text="{Binding Item1}" HorizontalOptions="Center" VerticalOptions="Center"/>
<Span Text="{Binding Item2}" HorizontalOptions="Center" VerticalOptions="Center"/>
<Span Text="{Binding Item3}" HorizontalOptions="Center" VerticalOptions="Center"/>
<Span Text="{Binding Item4}" HorizontalOptions="Center" VerticalOptions="Center"/>
<Span Text="{Binding Item5}" HorizontalOptions="Center" VerticalOptions="Center"/>
<Span Text="{Binding Item6}" HorizontalOptions="Center" VerticalOptions="Center"/>
</FormattedString>
</Label.FormattedText>
</Label>
Layer that over an Entry with TextColor of Transparent. when the user inputs values simply set Item1 - Item6 to display as desired.

Related

Why an Entry control do not receive the input from user in Xamarin Forms?

enter image description hereI want to implement the xamarin essentials map, but with a floating search for the pins that will appear on this map. I'm using a grid to divide the grid's rows and thus use the first row for the map and the second to show a cardview related to the selected pin. I put the search control in row 0 so that it seems to float on the map.
I couldn't get the focus of the search control to work. I don't know if I'm implementing the InputTransparent property correctly.
Any ideas?
<Grid InputTransparent="False">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="140"/>
</Grid.RowDefinitions>
<maps:Map
x:Name="map"
Grid.Column="0"
Grid.Row="0"
Grid.RowSpan="2"
MapType="Street"
HasZoomEnabled="True"
IsShowingUser="True"
InputTransparent="False"
MoveToLastRegionOnLayoutChange="false"
>
</maps:Map>
<StackLayout Grid.Row="0" Grid.Column="0" InputTransparent="True">
<Frame
Margin="20,40,20,0"
Padding="0"
BorderColor="{StaticResource BlackColor}"
CornerRadius="8"
HeightRequest="35">
<Grid VerticalOptions="CenterAndExpand">
<Grid.RowDefinitions>
<RowDefinition Height="35" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="35" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="35" />
</Grid.ColumnDefinitions>
<Image
Grid.Row="0"
Grid.Column="0"
HeightRequest="20"
HorizontalOptions="Center"
Source="ic_search_bar"
VerticalOptions="Center"
WidthRequest="20" />
<controls:CustomEntry
x:Name="entrySearch"
Grid.Row="0"
Grid.Column="1"
FontSize="14"
HeightRequest="35"
HorizontalOptions="FillAndExpand"
HorizontalTextAlignment="Start"
Keyboard="Text"
Placeholder="¿Qué se te antoja hoy?"
PlaceholderColor="#979797"
ReturnCommand="{Binding SearchCommand}"
InputTransparent="False"
ReturnType="Search"
Text="{Binding SearchText}"
TextChanged="entrySearch_TextChanged"
VerticalOptions="FillAndExpand"
VerticalTextAlignment="Center" />
<Image
Grid.Row="0"
Grid.Column="2"
HeightRequest="15"
HorizontalOptions="Center"
Source="ic_clear_search.png"
VerticalOptions="Center"
WidthRequest="15">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding ClearSearchCommand}" NumberOfTapsRequired="1" />
</Image.GestureRecognizers>
</Image>
</Grid>
</Frame>
</StackLayout>
</Grid>
I try to use the property in many parts of the code
From the docs on InputTransparent
true if neither the element nor its children should receive input and
should, instead, pass inputs to the elements that are visually behind
the current visual element
Your stackLayout is transparent so it’s children, including the Entry, are also transparent
You might be thinking InputTransparent does the opposite of what it actually does. True makes an area effectively invisible to touch; touch goes through it.
If you want an element to be touchable, it has to be "False". BUT all its ancestors must also NOT BLOCK touch.
If you really mean "True", but you have children you want to click on, do this:
<SomeLayoutNameHere InputTransparent="True" CascadeInputTransparent="False" ...>
That allows children to specify whether they can receive touch (InputTransparent=False), or are invisible to touch (=True).
"False" is the default.

Xamarin: First call to InitializeComponent slow

The problem is that the first call to a page's InitializeComponent is very slow. Thus the page transition animation is laggy for the first time. StackLayout with a few Labels and a Grid can take like 70 ms on my phone. I removed almost everything from the page and tried to find a bottle neck but it seems that even an empty grid adds a significant amount of time. So my full page takes something like 180 ms and when it's loaded for the first time there is almost no animation and it looks like a freezing app. Consecutive animations take like 15~20 ms.
Answering your potential questions: Yes, I have XAML compilation enabled. And yes, I've tried Release build but it doesn't help much.
Updated
I have added a button and a static grid to an items detail of default Xamarin application created in Visual Studio.
This is current content of the page:
<StackLayout Spacing="20" Padding="15">
<Label Text="Text:" FontSize="Medium" />
<Label Text="{Binding Text}" FontSize="Small"/>
<Label Text="Description:" FontSize="Medium" />
<Label Text="{Binding Description}" FontSize="Small"/>
<Button Text="{Binding Text}" />
<Grid RowSpacing="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" Text="Coins:" FontAttributes="Bold" />
<Label Grid.Row="0" Grid.Column="1" Text="111" HorizontalTextAlignment="End" />
<Label Grid.Row="0" Grid.Column="2" Text="Total coins:" FontAttributes="Bold" />
<Label Grid.Row="0" Grid.Column="3" Text="100000" HorizontalTextAlignment="End"/>
<Label Grid.Row="1" Grid.Column="0" Text="Gold:" FontAttributes="Bold" />
<Label Grid.Row="1" Grid.Column="1" Text="222" HorizontalTextAlignment="End" />
<Label Grid.Row="1" Grid.Column="2" Text="Table gold:" FontAttributes="Bold" />
<Label Grid.Row="1" Grid.Column="3" Text="120 " HorizontalTextAlignment="End"/>
</Grid>
</StackLayout>
And this is how I measure the time:
public partial class ItemDetailPage : ContentPage
{
public ItemDetailPage()
{
var start = DateTime.Now.ToUniversalTime().Millisecond;
InitializeComponent();
var end = DateTime.Now.ToUniversalTime().Millisecond;
Debug.WriteLine($"ItemDetailPage.InitializeComponent: {end - start}");
BindingContext = new ItemDetailViewModel();
}
}

Equal sized labels in Xamarin Forms

With a horizontal StackLayout, I want to display 3 labels equal width across the screen. I don't want to use a WidthRequest property, but, rather, I want each label to be the same size with the content centered in the "box". And I want the labels to resize according to the device they are running on. So 3 labels, equal width, no matter the device.
I know this can be done with a Grid (Width="Auto"), but is it possible with a horizontally aligned StackLayout?
I was thinking this would work...
<StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand">
<Label Text="aaaa"
HorizontalOptions="FillAndExpand"
HorizontalTextAlignment="Center"
BackgroundColor="Blue" />
<Label Text="aaaaaaaaaaaa"
HorizontalOptions="FillAndExpand"
HorizontalTextAlignment="Center"
BackgroundColor="Green" />
<Label Text="aa"
HorizontalOptions="FillAndExpand"
HorizontalTextAlignment="Center"
BackgroundColor="Red" />
</StackLayout>
But it just resulted in this...
Cause: When you add labels in stackLayout ,stackLayout will not make the subviews fit the size.
Solution:
Put the labels in a Grid. Refer the following code.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Text="aaaa" BackgroundColor="Blue" />
<Label Grid.Row="0" Grid.Column="1" Text="aaaaaaaaaaaa" BackgroundColor="Green"/>
<Label Grid.Row="0" Grid.Column="2" Text="aa" BackgroundColor="Red" />
</Grid>

How can I make two labels inside two grids appear far left and far right?

I have this XAML:
<Grid BackgroundColor="Red">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<Grid Grid.Column="0" HorizontalOptions="Start">
<Label Text="X" />
</Grid>
<Grid Grid.Column="1" HorizontalOptions="EndAndExpand">
<Label Text="Y" HorizontalOptions="End" />
</Grid>
</Grid>
I wanted to see something like this with a red background from one side to another:
X Y
However what happens is this with a red background from one side to another:
X Y
Can someone give me advice on how I can achieve the effect I want and what might be going wrong? Note that the Label Text that's currently "Y" could actually be much longer and more than half of the width of the screen. Here I just used one character to simplify the question.
Set your main Grid to HorizontalOptions="FillAndExpand" and your columns to take up the full width with *.
Now, you don't need the extra wrapping Grids. You could use them, but it will complicate things. Then set the Labels to HorizontalOptions="Start" and End respectively.
<Grid BackgroundColor="Red" VerticalOptions="Center" HorizontalOptions="FillAndExpand">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Text="X" HorizontalOptions="Start"/>
<Label Grid.Column="1" Text="Y" HorizontalOptions="End" />
</Grid>
Resulting in:

Is there a way that I can set the width of two buttons appearing at the bottom of a page to 75?

I have code that displays two buttons at the bottom of my screen:
<Grid VerticalOptions="FillAndExpand" Padding="10" IsVisible="{Binding TwoBtnsVisible}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Grid.Column="0" BorderColor="#999999" VerticalOptions="FillAndExpand" Style="{StaticResource pointButton2}" Text="Don't Know" Command="{Binding NButtonClickedCommand}" />
<Button Grid.Column="1" BorderColor="#999999" VerticalOptions="FillAndExpand" Style="{StaticResource pointButton2}" Text="Easy" Command="{Binding YButtonClickedCommand}" />
</Grid>
The width of the buttons fills the screen with a small amount to spare on either side and in between.
I would like to set the width of the buttons but it seems to not be possible. Is there some way I could do this so that each button is still spaced out nicely but has a width of just 75?
The grid size will be based upon its parent container (that you did not include), so assuming you do not want to alter it, you can use ColumnSpan. With 6 Proportional(*) columns, and a button width of two columns, that works out to:
100% width / 6 columns * 2 buttons of 2 column width = 66% of total width and thus 16.5% padding on the sides of the buttons
<Grid VerticalOptions="FillAndExpand" Padding="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Grid.Column="1" Grid.ColumnSpan="2" BackgroundColor="Red" BorderColor="#999999" VerticalOptions="FillAndExpand" Text="Don't Know" />
<Button Grid.Column="3" Grid.ColumnSpan="2" BackgroundColor="Red" BorderColor="#999999" VerticalOptions="FillAndExpand" Text="Easy" />
</Grid>
Try adding this two properties to each button.
It *should display them as you describe.
WidthRequest="75"
HorizontalOptions="Center"

Resources