Hello, I've got what may be an overly complex system for themes in my app.
I have 3 different ResourceDictionaries that I apply in my apps startup.
In order of loading they are
FontSizeDictionary ->Dimension specific
ColorThemeDictionary -> User chosen color scheme.
and
AppStylesDictionary -> Application wide styles for controls.
The app checks the screen size, then picks the appropriate fonts dictionary. Since this is being done based on screen size I didn't think using <OnIdiom>
would be an appropriate solution since resolutions can be different on different device and screen sizes.
After it's picked the font sizes, the app selects the color theme the user has chosen. This dictionary is merged, and finally the styles dictionary is merged into the app.
When loading the AppStylesDictionary, I am getting an exception thrown about an invalid cast for one of my settings
Here is the code for how the Themes are applied
App.xaml.cs
....
/// <summary>
/// Switch the theme from light to dark or vice versa.
/// </summary>
public void ChangeTheme()
{
try
{
// check if the theme key exists, if not default it to the light theme.
if (!AppSettingsFunctions.CheckKey("App_Theme"))
{
AppSettingsFunctions.SaveSettingData("App_Theme", 0);
}
var theme = AppSettingsFunctions.GetSetting("App_Theme");
if (string.IsNullOrEmpty(theme.ToString()))
{
theme = Theme.Light;
}
var themeChoice = Convert.ToInt32(theme, CultureInfo.InvariantCulture);
if (IsASmallDevice())
{
dictionary.MergedDictionaries.Add(Themes.SmallFonts.SharedInstance);
}
else
{
dictionary.MergedDictionaries.Add(Themes.MediumFonts.SharedInstance);
}
switch (themeChoice)
{
case (int)Theme.Dark:
dictionary.MergedDictionaries.Add(Themes.DarkThemeDictionary.SharedInstance);
break;
case (int)Theme.Light:
dictionary.MergedDictionaries.Add(Themes.LightThemeDictionary.SharedInstance);
break;
case (int)Theme.Colorful:
dictionary.MergedDictionaries.Add(Themes.ColorfulThemeDictionary.SharedInstance);
break;
default:
dictionary.MergedDictionaries.Add(Themes.LightThemeDictionary.SharedInstance);
break;
}
//Finally apply the styles for the application
this.Resources.MergedDictionaries.Add(Themes.AppStyles.SharedInstance);
}
catch (Exception ex)
{
DebugTools.LogException(ex);
}
}
In my FontsDictionaries I have the variables specified as Int16
values
<ResourceDictionary
x:Class="BoomStick.Themes.MediumFonts"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
<x:Int32 x:Key="SmallFont">11</x:Int32>
<x:Int32 x:Key="MediumFont">13</x:Int32>
<x:Int32 x:Key="LargeFont">15</x:Int32>
<x:Int32 x:Key="BorderFont">17</x:Int32>
<x:Int32 x:Key="LabelFont">15</x:Int32>
<x:Int32 x:Key="DataFont">14</x:Int32>
</ResourceDictionary>
The odd part is, when I use the font sizes in the AppStyles dictionary it works for one type of style definition but not another.
Here is an excerpt from the AppStylesDictionary that demonstrates my issue
<!--Defines error label style This gets applied to <Label> objects-->
<Style x:Key="Notation" TargetType="Label">
<Setter Property="TextColor" Value="{StaticResource Key=cAltTextColor}" />
<Setter Property="FontAttributes" Value="Bold" />
<Setter Property="FontSize" Value="{StaticResource Key=MediumFont}" />
<Setter Property="Margin" Value="-5,5,0,0" />
<Setter Property="FontFamily" Value="{StaticResource Key=Baloo2-SemiBold}" />
<Setter Property="LineBreakMode" Value="WordWrap" />
</Style>
<Style
ApplyToDerivedTypes="True"
CanCascade="True"
TargetType="textinputlayout:SfTextInputLayout">
<Setter Property="UnfocusedColor" Value="{StaticResource Key=cHilightColor}" />
<Setter Property="FocusedColor" Value="{StaticResource Key=cTextColor}" />
<Setter Property="ContainerType" Value="None" />
<Setter Property="HintLabelStyle">
<Setter.Value>
<textinputlayout:LabelStyle
FontAttributes="Bold"
FontFamily="{StaticResource Key=Baloo2-SemiBold}"
FontSize="{StaticResource Key=MediumFont}" />
</Setter.Value>
</Setter>
<Setter Property="ErrorLabelStyle">
<Setter.Value>
<textinputlayout:LabelStyle
FontAttributes="Italic"
FontFamily="{StaticResource Key=Baloo2-SemiBold}"
FontSize="{StaticResource Key=SmallFont}" />
</Setter.Value>
</Setter>
</Style>
In the above code, the StaticResource used for the <Label>
style is fine, but later when it's used in the styling for the textinputlayout control, it throws an exception saying that the specified cast is invalid. If I hard code the values it works fine. Also the FontFamily
flag is being populated just fine. I have tried specifying the font sizes using <x:Int16(32,64)>
and also tried them as <x:String>
For the time being I've resigned myself to manually coding the sizes, but it would be nice to be able to get this working.
Cheers!