Here's a complete implementation of a digital clock and timer in .NET MAUI. This solution includes both a real-time clock display and a countdown timer functionality.
1. Create the ViewModel
First, let's create a ViewModel to handle the time and timer logic:
using System.ComponentModel; using System.Runtime.CompilerServices; using System.Timers; public class ClockTimerViewModel : INotifyPropertyChanged { private Timer _clockTimer; private Timer _countdownTimer; private TimeSpan _remainingTime; private bool _isTimerRunning; private string _timerButtonText = "Start"; public event PropertyChangedEventHandler PropertyChanged; public DateTime CurrentTime => DateTime.Now; public TimeSpan RemainingTime { get => _remainingTime; set { if (_remainingTime != value) { _remainingTime = value; OnPropertyChanged(); OnPropertyChanged(nameof(RemainingTimeDisplay)); } } } public string RemainingTimeDisplay => RemainingTime.ToString(@"hh\:mm\:ss"); public bool IsTimerRunning { get => _isTimerRunning; set { if (_isTimerRunning != value) { _isTimerRunning = value; OnPropertyChanged(); TimerButtonText = _isTimerRunning ? "Stop" : "Start"; } } } public string TimerButtonText { get => _timerButtonText; set { if (_timerButtonText != value) { _timerButtonText = value; OnPropertyChanged(); } } } public int Hours { get; set; } = 0; public int Minutes { get; set; } = 0; public int Seconds { get; set; } = 0; public ClockTimerViewModel() { // Initialize clock timer (updates every second) _clockTimer = new Timer(1000); _clockTimer.Elapsed += (s, e) => OnPropertyChanged(nameof(CurrentTime)); _clockTimer.Start(); // Initialize countdown timer _countdownTimer = new Timer(1000); _countdownTimer.Elapsed += CountdownTimerElapsed; } private void CountdownTimerElapsed(object sender, ElapsedEventArgs e) { if (RemainingTime.TotalSeconds <= 0) { Device.BeginInvokeOnMainThread(() => { IsTimerRunning = false; _countdownTimer.Stop(); // You could add an alert here when timer completes }); return; } RemainingTime = RemainingTime.Subtract(TimeSpan.FromSeconds(1)); } public void StartStopTimer() { if (IsTimerRunning) StopTimer(); else StartTimer(); } private void StartTimer() { if (RemainingTime.TotalSeconds <= 0) { // Set initial time from pickers RemainingTime = new TimeSpan(Hours, Minutes, Seconds); } if (RemainingTime.TotalSeconds > 0) { IsTimerRunning = true; _countdownTimer.Start(); } } private void StopTimer() { IsTimerRunning = false; _countdownTimer.Stop(); } public void ResetTimer() { StopTimer(); RemainingTime = new TimeSpan(Hours, Minutes, Seconds); } protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
2. Create the XAML View
Now, let's create the UI in XAML:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:viewmodels="clr-namespace:YourNamespace.ViewModels" x:Class="YourNamespace.MainPage" Title="MAUI Clock & Timer"> <ContentPage.BindingContext> <viewmodels:ClockTimerViewModel /> </ContentPage.BindingContext> <ScrollView> <VerticalStackLayout Spacing="20" Padding="20"> <!-- Digital Clock Section --> <Frame BorderColor="LightGray" CornerRadius="10" Padding="20"> <VerticalStackLayout Spacing="10"> <Label Text="Digital Clock" FontSize="Title" HorizontalOptions="Center"/> <Label Text="{Binding CurrentTime, StringFormat='{0:HH:mm:ss}'}" FontSize="48" HorizontalOptions="Center" FontAttributes="Bold"/> <Label Text="{Binding CurrentTime, StringFormat='{0:dddd, MMMM d, yyyy}'}" FontSize="16" HorizontalOptions="Center"/> </VerticalStackLayout> </Frame> <!-- Timer Section --> <Frame BorderColor="LightGray" CornerRadius="10" Padding="20"> <VerticalStackLayout Spacing="15"> <Label Text="Timer" FontSize="Title" HorizontalOptions="Center"/> <!-- Timer Display --> <Label Text="{Binding RemainingTimeDisplay}" FontSize="48" HorizontalOptions="Center" FontAttributes="Bold"/> <!-- Time Input --> <HorizontalStackLayout Spacing="10" HorizontalOptions="Center"> <Picker Title="H" ItemsSource="{Binding HourOptions}" SelectedIndex="{Binding Hours}" WidthRequest="80"/> <Label Text=":" VerticalTextAlignment="Center"/> <Picker Title="M" ItemsSource="{Binding MinuteSecondOptions}" SelectedIndex="{Binding Minutes}" WidthRequest="80"/> <Label Text=":" VerticalTextAlignment="Center"/> <Picker Title="S" ItemsSource="{Binding MinuteSecondOptions}" SelectedIndex="{Binding Seconds}" WidthRequest="80"/> </HorizontalStackLayout> <!-- Timer Controls --> <HorizontalStackLayout Spacing="20" HorizontalOptions="Center"> <Button Text="{Binding TimerButtonText}" Command="{Binding StartStopTimerCommand}" WidthRequest="100"/> <Button Text="Reset" Command="{Binding ResetTimerCommand}" WidthRequest="100"/> </HorizontalStackLayout> </VerticalStackLayout> </Frame> </VerticalStackLayout> </ScrollView> </ContentPage>
3. Update the ViewModel with Commands and Options
Add these additional properties to your ViewModel:
public ClockTimerViewModel() { // ... existing constructor code ... StartStopTimerCommand = new Command(StartStopTimer); ResetTimerCommand = new Command(ResetTimer); // Initialize picker options HourOptions = Enumerable.Range(0, 24).Select(i => i.ToString()).ToList(); MinuteSecondOptions = Enumerable.Range(0, 60).Select(i => i.ToString()).ToList(); } public ICommand StartStopTimerCommand { get; } public ICommand ResetTimerCommand { get; } public List<string> HourOptions { get; } public List<string> MinuteSecondOptions { get; }
4. Add Platform-Specific Code for Android (Optional)
For Android, you might want to add this to your MauiProgram.cs
to ensure timers work when the app is in the background:
// In your MauiProgram.CreateMauiApp() method #if ANDROID Microsoft.Maui.Handlers.WidgetHandler.LayoutManager.AlwaysMeasure = true; #endif
5. Complete Code-Behind
Here's the code-behind for the page (though it's mostly empty since we're using MVVM):
public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); } }
Features of This Implementation:
Digital Clock:
Shows current time updating every second
Displays the current date
Timer:
Countdown timer with hours, minutes, and seconds
Start/Stop and Reset functionality
Time selection via pickers
Visual display of remaining time
MVVM Architecture:
Clean separation of concerns
Data binding for automatic UI updates
Commands for button actions
Customization Options:
You can change the fonts, colors, and sizes in the XAML
Add alarm sounds when the timer completes (use
IAudio
service)Add vibration when timer completes (use
IVibration
service)Add more timer presets
Implement multiple timers
This implementation provides a complete, functional digital clock and timer in .NET MAUI with a clean UI and proper separation of concerns using the MVVM pattern.
No comments:
Post a Comment