Tema de una aplicación
Las aplicaciones de interfaz de usuario de aplicaciones multiplataforma de .NET (.NET MAUI) pueden responder a los cambios de estilo dinámicamente en tiempo de ejecución mediante la DynamicResource extensión de marcado. Esta extensión de marcado es similar a la StaticResource extensión de marcado, en que ambas usan una clave de diccionario para capturar un valor de .ResourceDictionary Sin embargo, aunque la StaticResource extensión de marcado realiza una búsqueda de diccionario único, la DynamicResource extensión de marcado mantiene un vínculo a la clave del diccionario. Por lo tanto, si el valor asociado a la clave se reemplaza, el cambio se aplica a VisualElement. Esto permite implementar el tema en tiempo de ejecución en aplicaciones MAUI de .NET.
El proceso para implementar el creación de temáticas en tiempo de ejecución en una aplicación MAUI de .NET es el siguiente:
- Defina los recursos de cada tema de .
ResourceDictionaryPara obtener más información, vea Definir temas. - Establezca un tema predeterminado en el archivo App.xaml de la aplicación. Para obtener más información, vea Establecer un tema predeterminado.
- Consumir recursos de tema en la aplicación, mediante la extensión de
DynamicResourcemarcado. Para obtener más información, consulte Consumo de recursos de temas. - Agregue código para cargar un tema en tiempo de ejecución. Para obtener más información, consulte Carga de un tema en tiempo de ejecución.
Importante
Use la StaticResource extensión de marcado si no es necesario cambiar el tema de la aplicación en tiempo de ejecución.
En la captura de pantalla siguiente se muestran páginas temáticas, con la aplicación iOS con un tema claro y la aplicación android con un tema oscuro:
Nota
Cambiar un tema en tiempo de ejecución requiere el uso de estilos XAML y no es posible usar CSS.
.NET MAUI también tiene la capacidad de responder a los cambios de tema del sistema. El tema del sistema puede cambiar por diversos motivos, según la configuración del dispositivo. Esto incluye el tema del sistema que el usuario cambia explícitamente, cambia debido a la hora del día y cambia debido a factores ambientales como la luz baja. Para obtener más información, consulte Responder a los cambios del tema del sistema.
Definición de temas
Un tema se define como una colección de objetos de recursos almacenados en .ResourceDictionary
En el ejemplo siguiente se muestra un para ResourceDictionary un tema claro denominado LightTheme:
<ResourceDictionary xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ThemingDemo.LightTheme">
<Color x:Key="PageBackgroundColor">White</Color>
<Color x:Key="NavigationBarColor">WhiteSmoke</Color>
<Color x:Key="PrimaryColor">WhiteSmoke</Color>
<Color x:Key="SecondaryColor">Black</Color>
<Color x:Key="PrimaryTextColor">Black</Color>
<Color x:Key="SecondaryTextColor">White</Color>
<Color x:Key="TertiaryTextColor">Gray</Color>
<Color x:Key="TransparentColor">Transparent</Color>
</ResourceDictionary>
En el ejemplo siguiente se muestra un para ResourceDictionary un tema oscuro denominado DarkTheme:
<ResourceDictionary xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ThemingDemo.DarkTheme">
<Color x:Key="PageBackgroundColor">Black</Color>
<Color x:Key="NavigationBarColor">Teal</Color>
<Color x:Key="PrimaryColor">Teal</Color>
<Color x:Key="SecondaryColor">White</Color>
<Color x:Key="PrimaryTextColor">White</Color>
<Color x:Key="SecondaryTextColor">White</Color>
<Color x:Key="TertiaryTextColor">WhiteSmoke</Color>
<Color x:Key="TransparentColor">Transparent</Color>
</ResourceDictionary>
Cada ResourceDictionary uno contiene Color recursos que definen sus respectivos temas, con cada uno ResourceDictionary con valores de clave idénticos. Para obtener más información sobre los diccionarios de recursos, consulte Diccionarios de recursos.
Importante
Se requiere un archivo de código subyacente para cada ResourceDictionary, que llama al InitializeComponent método . Esto es necesario para que se pueda crear un objeto CLR que represente el tema elegido en tiempo de ejecución.
Establecer un tema predeterminado
Una aplicación requiere un tema predeterminado, de modo que los controles tengan valores para los recursos que consumen. Un tema predeterminado se puede establecer combinando el tema ResourceDictionary en el nivel ResourceDictionary de aplicación definido en App.xaml:
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ThemingDemo.App">
<Application.Resources>
<ResourceDictionary Source="Themes/LightTheme.xaml" />
</Application.Resources>
</Application>
Para obtener más información sobre cómo combinar diccionarios de recursos, consulte Diccionarios de recursos combinados.
Consumo de recursos de tema
Cuando una aplicación quiere consumir un recurso almacenado en un ResourceDictionary que representa un tema, debe hacerlo con la DynamicResource extensión de marcado. Esto garantiza que si se selecciona un tema diferente en tiempo de ejecución, se aplicarán los valores del nuevo tema.
En el ejemplo siguiente se muestran tres estilos de que se pueden aplicar a todos los Label objetos de la aplicación:
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ThemingDemo.App">
<Application.Resources>
<Style x:Key="LargeLabelStyle"
TargetType="Label">
<Setter Property="TextColor"
Value="{DynamicResource SecondaryTextColor}" />
<Setter Property="FontSize"
Value="30" />
</Style>
<Style x:Key="MediumLabelStyle"
TargetType="Label">
<Setter Property="TextColor"
Value="{DynamicResource PrimaryTextColor}" />
<Setter Property="FontSize"
Value="25" />
</Style>
<Style x:Key="SmallLabelStyle"
TargetType="Label">
<Setter Property="TextColor"
Value="{DynamicResource TertiaryTextColor}" />
<Setter Property="FontSize"
Value="15" />
</Style>
</Application.Resources>
</Application>
Estos estilos se definen en el diccionario de recursos de nivel de aplicación, para que varias páginas puedan consumirlos. Cada estilo consume recursos de tema con la extensión de DynamicResource marcado.
A continuación, estas páginas consumen estos estilos:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:ThemingDemo"
x:Class="ThemingDemo.UserSummaryPage"
Title="User Summary"
BackgroundColor="{DynamicResource PageBackgroundColor}">
...
<ScrollView>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="200" />
<RowDefinition Height="120" />
<RowDefinition Height="70" />
</Grid.RowDefinitions>
<Grid BackgroundColor="{DynamicResource PrimaryColor}">
<Label Text="Face-Palm Monkey"
VerticalOptions="Center"
Margin="15"
Style="{StaticResource MediumLabelStyle}" />
...
</Grid>
<StackLayout Grid.Row="1"
Margin="10">
<Label Text="This monkey reacts appropriately to ridiculous assertions and actions."
Style="{StaticResource SmallLabelStyle}" />
<Label Text=" • Cynical but not unfriendly."
Style="{StaticResource SmallLabelStyle}" />
<Label Text=" • Seven varieties of grimaces."
Style="{StaticResource SmallLabelStyle}" />
<Label Text=" • Doesn't laugh at your jokes."
Style="{StaticResource SmallLabelStyle}" />
</StackLayout>
...
</Grid>
</ScrollView>
</ContentPage>
Cuando un recurso de tema se consume directamente, se debe consumir con la DynamicResource extensión de marcado. Sin embargo, cuando se consume un estilo que usa la DynamicResource extensión de marcado, se debe consumir con la StaticResource extensión de marcado.
Para obtener más información sobre el estilo, consulta Aplicación de estilo mediante XAML. Para obtener más información sobre la DynamicResource extensión de marcado, vea Estilos dinámicos.
Cargar un tema en tiempo de ejecución
Cuando se selecciona un tema en tiempo de ejecución, una aplicación debe:
- Quite el tema actual de la aplicación. Esto se logra borrando la
MergedDictionariespropiedad del nivelResourceDictionaryde aplicación . - Cargue el tema seleccionado. Esto se logra agregando una instancia del tema seleccionado a la
MergedDictionariespropiedad del nivelResourceDictionaryde aplicación .
Los VisualElement objetos que establezcan propiedades con la DynamicResource extensión de marcado aplicarán los nuevos valores de tema. Esto ocurre porque la DynamicResource extensión de marcado mantiene un vínculo a las claves de diccionario. Por lo tanto, cuando se reemplazan los valores asociados a las claves, los cambios se aplican a los VisualElement objetos .
En la aplicación de ejemplo, se selecciona un tema a través de una página modal que contiene .Picker El código siguiente muestra el OnPickerSelectionChanged método , que se ejecuta cuando cambia el tema seleccionado:
En el ejemplo siguiente se muestra cómo quitar el tema actual y cargar un nuevo tema:
ICollection<ResourceDictionary> mergedDictionaries = Application.Current.Resources.MergedDictionaries;
if (mergedDictionaries != null)
{
mergedDictionaries.Clear();
mergedDictionaries.Add(new DarkTheme());
}
Examinar el ejemplo