Finishing the App
We have a fully functional calculator app, but there are still some things we can do to further customize and refine the app. In this module, we will look at the ThemeService
from Uno.Extensions and use this to toggle between light and dark theme in the app. Then we will finish by overriding the default colors to give the app a more custom look and feel.
Adding the ThemeService
We need to update the constructor of our DataContext
(MVVM ViewModel) to use the IThemeService
. First, we need to update the initial value of the IsDark
property to use the IThemeServicce.IsDark
property. Because the IThemeService
may still update the initial theme as initializes, we will want to hook into its ThemeChanged
event and update the IsDark
property when the theme changes. Finally, we will want to update the theme when the IsDark
property is changed by the user.
Update the MainViewModel
with the following constructor, _themeService
field and IsDark
property:
namespace SimpleCalculator;
public partial class MainViewModel : ObservableObject
{
private readonly IThemeService _themeService;
public MainViewModel(IThemeService themeService)
{
_themeService = themeService;
IsDark = _themeService.IsDark;
_themeService.ThemeChanged += (_, _) => IsDark = _themeService.IsDark;
}
private bool _isDark;
public bool IsDark
{
get => _isDark;
set
{
if (SetProperty(ref _isDark, value))
{
_themeService.SetThemeAsync(value ? AppTheme.Dark : AppTheme.Light);
}
}
}
[ObservableProperty]
private Calculator _calculator = new();
[RelayCommand]
private void Input(string key) =>
Calculator = Calculator.Input(key);
}
With our ViewModel
updated we need to update our MainPage.xaml.cs file so that we initialize the MainViewModel
with an IThemeService
instance.
namespace SimpleCalculator;
public partial class MainPage : Page
{
public MainPage()
{
InitializeComponent();
DataContext = new MainViewModel(this.GetThemeService());
}
}
Customizing the Color Palette
So far we have the default Uno Material color palette from Uno.Material
with some overrides from the new app template. We can further customize the color palette by updating the color overrides in the Styles folder of our SimpleCalculator project.
ColorPaletteOverride.xaml code contents (collapsed for brevity)
<ResourceDictionary xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Light">
<!--Background-->
<Color x:Key="BackgroundColor">#FCFCFF</Color>
<!--OnBackground-->
<Color x:Key="OnBackgroundColor">#1A1C1E</Color>
<!--Primary-->
<Color x:Key="PrimaryColor">#006399</Color>
<Color x:Key="PrimaryContainerColor">#CDE5FF</Color>
<Color x:Key="PrimaryInverseColor">#95CCFF</Color>
<!--OnPrimary-->
<Color x:Key="OnPrimaryColor">#FFFFFF</Color>
<Color x:Key="OnPrimaryContainerColor">#001D32</Color>
<!--Secondary-->
<Color x:Key="SecondaryColor">#51606F</Color>
<Color x:Key="SecondaryContainerColor">#D5E4F6</Color>
<!--Secondary-->
<Color x:Key="OnSecondaryColor">#FFFFFF</Color>
<Color x:Key="OnSecondaryContainerColor">#0E1D2A</Color>
<!--Tertiary-->
<Color x:Key="TertiaryColor">#00658D</Color>
<Color x:Key="TertiaryContainerColor">#C6E7FF</Color>
<!--OnTertiary-->
<Color x:Key="OnTertiaryColor">#FFFFFF</Color>
<Color x:Key="OnTertiaryContainerColor">#001E2D</Color>
<!--Surface-->
<Color x:Key="SurfaceColor">#FCFCFF</Color>
<Color x:Key="SurfaceVariantColor">#DEE3EB</Color>
<Color x:Key="SurfaceInverseColor">#2F3033</Color>
<Color x:Key="SurfaceTintColor">#006399</Color>
<!--OnSurface-->
<Color x:Key="OnSurfaceColor">#1A1C1E</Color>
<Color x:Key="OnSurfaceVariantColor">#42474E</Color>
<Color x:Key="OnSurfaceInverseColor">#F0F0F4</Color>
<!--Outline-->
<Color x:Key="OutlineColor">#72777F</Color>
<Color x:Key="OutlineVariantColor">#C2C7CF</Color>
<!--Error-->
<Color x:Key="ErrorColor">#BA1A1A</Color>
<Color x:Key="ErrorContainerColor">#FFDAD6</Color>
<!--OnError-->
<Color x:Key="OnErrorColor">#FFFFFF</Color>
<Color x:Key="OnErrorContainerColor">#410002</Color>
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<!--Background-->
<Color x:Key="BackgroundColor">#1A1C1E</Color>
<!--OnBackground-->
<Color x:Key="OnBackgroundColor">#E2E2E5</Color>
<!--Primary-->
<Color x:Key="PrimaryColor">#95CCFF</Color>
<Color x:Key="PrimaryContainerColor">#004A75</Color>
<Color x:Key="PrimaryInverseColor">#006399</Color>
<!--OnPrimary-->
<Color x:Key="OnPrimaryColor">#003352</Color>
<Color x:Key="OnPrimaryContainerColor">#CDE5FF</Color>
<!--Secondary-->
<Color x:Key="SecondaryColor">#B9C8DA</Color>
<Color x:Key="SecondaryContainerColor">#3A4857</Color>
<!--OnSecondary-->
<Color x:Key="OnSecondaryColor">#233240</Color>
<Color x:Key="OnSecondaryContainerColor">#D5E4F6</Color>
<!--Tertiary-->
<Color x:Key="TertiaryColor">#83CFFF</Color>
<Color x:Key="TertiaryContainerColor">#004C6B</Color>
<!--OnTertiary-->
<Color x:Key="OnTertiaryColor">#00344B</Color>
<Color x:Key="OnTertiaryContainerColor">#C6E7FF</Color>
<!--Surface-->
<Color x:Key="SurfaceColor">#335476</Color>
<Color x:Key="SurfaceVariantColor">#42474E</Color>
<Color x:Key="SurfaceInverseColor">#E2E2E5</Color>
<Color x:Key="SurfaceTintColor">#95CCFF</Color>
<!--OnSurface-->
<Color x:Key="OnSurfaceColor">#E2E2E5</Color>
<Color x:Key="OnSurfaceVariantColor">#C2C7CF</Color>
<Color x:Key="OnSurfaceInverseColor">#1A1C1E</Color>
<!--Outline-->
<Color x:Key="OutlineColor">#8C9198</Color>
<Color x:Key="OutlineVariantColor">#42474E</Color>
<!--Error-->
<Color x:Key="ErrorColor">#FFB4AB</Color>
<Color x:Key="ErrorContainerColor">#93000A</Color>
<!--OnError-->
<Color x:Key="OnErrorColor">#690005</Color>
<Color x:Key="OnErrorContainerColor">#FFDAD6</Color>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
With the color palette updated, we can now run the app again to see the updated look for our calculator. The final result will be similar to the image below:
Next Steps
Congratulations you have now created your first Uno app! The four permutations of the SimpleCalculator can be found within our Uno.Samples GitHub Repository.
To continue to learn more about Uno Platform be sure to check out the Uno Platform documentation and the Uno Platform samples.