How can I center align a fixed sized label and set font size to auto fill the label??

I made a Stop Watch page, simulated the Android and iOS stopwatch Apps.

My issue is that when I center align the label, the Binding text moves back and forth on iOS as the time changes to accommodate for the new updated text width. It stays centered on android though.

My approach to work around the issue is to HorizontalOptions:Center HorizontalTextAlignment: Start
in the label, but from there I need to size the font so it fills the width of the label.

XAML

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage x:Class="Cross11AthleticsApp.Pages.StopWatchPage"
         xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         Title="Stop Watch">

<ContentPage.Padding>
 <OnPlatform x:TypeArguments="Thickness" iOS="0, 20, 0, 0" />
 </ContentPage.Padding>

<StackLayout
 HorizontalOptions="FillAndExpand">

    <Label x:Name="lblTimerText"
       VerticalOptions="Center"
       HorizontalOptions="Center" />



<StackLayout
  Orientation="Horizontal"
  VerticalOptions="CenterAndExpand">

  <Button x:Name="buttonStartStop"
          HorizontalOptions="CenterAndExpand"
          BorderRadius="10"
          Clicked="OnButtonClicked"
          FontSize="Large"
          Text="Start" />



  <Button x:Name="buttonLap_Reset"
          HorizontalOptions="CenterAndExpand"
          BorderRadius="10"
          Clicked="OnbuttonLap_ResetClicked"
          FontSize="Large"
          IsEnabled="False"
          Text="Reset" />


</StackLayout>

<ListView x:Name="listLapTime"
          SeparatorColor="Blue"
             />


Code-behind

lblTimerText.Text = watch.Elapsed.ToString("mm':'ss':'ff");

 SizeChanged += (object sender, EventArgs args) =>
{
if (this.Width > 0)
lblTimerText.WidthRequest = this.Width / 1.2;
};

Thank you very much in advance!

Answers

  • ClintStLaurentClintStLaurent USUniversity ✭✭✭✭✭

    SizeChanged +=

    Where in your code is this? looks like you're subscribing to the event over and over and over if its in the same block as where you're changing the actual text.

  • DHCWizardDHCWizard USMember
    edited August 2016

    @ClintStLaurent

    Sorry I should have specified, It is for and change in page size, mainly during change in orientation, so that the label width = (thisPage) / 1.2.

    Regardless, my issue is to have the text stay in the same position as it is updating the elapsed time.

    Example:
    Initially, 00:00:00 is centered. But since 00:01:01 is technically thinner in width due to the character "1" is thinner than "0"...
    On android, the label is automatically centered while the text stays in a fixed position, vs iOS which it constantly takes the new center of each string value and causes it to jitter left to right.

    but here are the full pages:

    XAML

    <?xml version="1.0" encoding="utf-8" ?>
       <ContentPage x:Class="App.Pages.StopWatchPage"
         xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         Title="Stop Watch">
    
       <ContentPage.Padding>
       <OnPlatform x:TypeArguments="Thickness" iOS="0, 20, 0, 0" />
       </ContentPage.Padding>
    
     <StackLayout
      HorizontalOptions="FillAndExpand">
    
    <Label x:Name="lblTimerText"
       VerticalOptions="Center"
       HorizontalOptions="Center" />
    
    
    
     <StackLayout
     Orientation="Horizontal"
      VerticalOptions="CenterAndExpand">
    
    <Button x:Name="buttonStartStop"
          HorizontalOptions="CenterAndExpand"
          BorderRadius="10"
          Clicked="OnButtonClicked"
          FontSize="Large"
          Text="Start" />
    
    
    
      <Button x:Name="buttonLap_Reset"
          HorizontalOptions="CenterAndExpand"
          BorderRadius="10"
          Clicked="OnbuttonLap_ResetClicked"
          FontSize="Large"
          IsEnabled="False"
          Text="Reset" />
    
    
     </StackLayout>
    
      <ListView x:Name="listLapTime"
          SeparatorColor="Blue" />
    
    </StackLayout>
      </ContentPage>
    

    Code behind

    namespace App.Pages
     {
        public partial class StopWatchPage : IDisposable
     {
        Stopwatch watch;
    
        ObservableCollection<string> lapTime;
    
    
        CancellationTokenSource cancellationToken = null;
    
        public StopWatchPage()
        {  
            InitializeComponent();
    
    
    
            watch = new Stopwatch();
    
            watch.Reset();
            lblTimerText.Text = watch.Elapsed.ToString("mm':'ss':'ff");
            SizeChanged += (object sender, EventArgs args) =>
    
                        {
                            if (this.Width > 0)
                                lblTimerText.WidthRequest = this.Width / 1.2;
                        };
    
            lapTime = new ObservableCollection<string>();
    
            listLapTime.ItemsSource = lapTime;
        }
    
    
    
    
        void OnButtonClicked(object sender, EventArgs e)
        {
            if (this.watch.IsRunning)
            {
                watch.Stop();
                this.buttonStartStop.Text = "Start";
                this.buttonLap_Reset.Text = "Reset";
    
    
            }
    
            else if (this.cancellationToken != null)
            {
                if (!this.watch.IsRunning)
                {
                    this.watch.Start();
                    this.buttonStartStop.Text = "Stop";
    
                    this.buttonLap_Reset.Text = "Lap";
                }
            }
            else
            {
                this.cancellationToken = new CancellationTokenSource();
    
                this.watch.Start();
                this.buttonStartStop.Text = "Stop";
                this.buttonLap_Reset.IsEnabled = true;
                this.buttonLap_Reset.Text = "Lap";
                TimerRunning(this.cancellationToken.Token);
            }
        }
    
    
    
        void OnbuttonLap_ResetClicked(object sender, EventArgs e)
        {
            if (this.watch.IsRunning)
            {
    
    
                lapTime.Insert(0, watch.Elapsed.ToString("mm':'ss':'ff"));
            }
            else
            {
                watch.Reset();
                lapTime.Clear();
                buttonLap_Reset.Text = "Reset";
    
                this.cancellationToken = null;
            }
    
        }
    
    
    
    
        async void TimerRunning(CancellationToken token)
        {
    
            watch = Stopwatch.StartNew();
            while (!token.IsCancellationRequested)
            {
                try
                {
                    await Task.Delay(30 - (int)(watch.ElapsedMilliseconds % 30), token);
                }
                catch (TaskCanceledException)
                {
                }
    
    
                Device.BeginInvokeOnMainThread(() => this.lblTimerText.Text = watch.Elapsed.ToString("mm':'ss':'ff"));
            }
        }
    
    
    
        private void Dispose(bool v)
        {
            if (v)
            {
                cancellationToken.Dispose();
            }
        }
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    }
    }
    
Sign In or Register to comment.