Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Label that renders a countdown timer
using System;
using Xamarin.Forms;
namespace DK.InstantBetting.Views
{
public partial class CountdownLabel : Label
{
public static readonly BindableProperty TargetTimeProperty =
BindableProperty.Create("TargetTime", typeof(DateTime), typeof(CountdownLabel), DateTime.Now, propertyChanged: TargetTimeChanged);
public static readonly BindableProperty PrefixProperty =
BindableProperty.Create("Prefix", typeof(string), typeof(CountdownLabel), string.Empty);
public DateTime TargetTime
{
get => (DateTime)GetValue(TargetTimeProperty);
set => SetValue(TargetTimeProperty, value);
}
public string Prefix
{
get => (string)GetValue(PrefixProperty);
set => SetValue(PrefixProperty, value);
}
private bool _countdownRunning = false;
private bool _countdownValid = true;
private bool ShouldCountDown
{
get => _countdownValid && TargetTime > DateTime.Now;
}
public CountdownLabel()
{
InitializeComponent();
UpdateTitle();
StartCountdown();
}
~CountdownLabel()
{
StopCountdown();
}
private static void TargetTimeChanged(BindableObject bindable, object oldValue, object newValue)
{
CountdownLabel countdownLabel = bindable as CountdownLabel;
if (countdownLabel == null)
{
return;
}
countdownLabel.UpdateTitle();
countdownLabel.StartCountdown();
}
public void StartCountdown()
{
_countdownValid = true;
if (_countdownRunning || !ShouldCountDown)
{
return;
}
_countdownRunning = true;
Device.StartTimer(TimeSpan.FromSeconds(1), () =>
{
if (ShouldCountDown)
{
UpdateTitle();
}
_countdownRunning = ShouldCountDown;
return ShouldCountDown;
});
}
public void StopCountdown()
{
_countdownValid = false;
}
private void UpdateTitle()
{
Text = ShouldCountDown ?
FormatTimeSpan(TargetTime.Subtract(DateTime.Now)) :
"";
}
private const string DaysFormat = @"dd\:hh\:mm\:ss";
private const string HoursFormat = @"hh\:mm\:ss";
private const string MinutesFormat = @"mm\:ss";
private const string SecondsFormat = @"ss";
private string FormatTimeSpan(TimeSpan span)
{
string format;
if (span.Days > 0)
{
format = DaysFormat;
}
else if (span.Hours > 0)
{
format = HoursFormat;
}
else if (span.Minutes > 0)
{
format = MinutesFormat;
}
else
{
format = SecondsFormat;
}
return string.Format("{0}{1}", Prefix, span.ToString(format));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment