Tema di un'applicazione Xamarin.Forms
Xamarin.Forms le applicazioni possono rispondere alle modifiche di stile in modo dinamico in fase di esecuzione usando l'estensione di DynamicResource
markup. Questa estensione di markup è simile all'estensione StaticResource
di markup, in quanto entrambi usano una chiave del dizionario per recuperare un valore da un oggetto ResourceDictionary
. Tuttavia, mentre l'estensione StaticResource
di markup esegue una ricerca in un singolo dizionario, l'estensione DynamicResource
di markup mantiene un collegamento alla chiave del dizionario. Pertanto, se il valore associato alla chiave viene sostituito, la modifica viene applicata a VisualElement
. In questo modo è possibile implementare il tema di runtime nelle Xamarin.Forms applicazioni.
Il processo di implementazione del tema di runtime in un'applicazione Xamarin.Forms è il seguente:
- Definire le risorse per ogni tema in un oggetto
ResourceDictionary
. - Utilizzare le risorse del tema nell'applicazione usando l'estensione di
DynamicResource
markup. - Impostare un tema predefinito nel file App.xaml dell'applicazione.
- Aggiungere codice per caricare un tema in fase di esecuzione.
Importante
Usare l'estensione StaticResource
di markup se non è necessario modificare il tema dell'app in fase di esecuzione.
Gli screenshot seguenti mostrano pagine con tema tema, con l'applicazione iOS usando un tema chiaro e l'applicazione Android usando un tema scuro:
Nota
La modifica di un tema in fase di esecuzione richiede l'uso degli stili XAML e non è attualmente possibile tramite CSS.
Definire i temi
Un tema viene definito come una raccolta di oggetti risorsa archiviati in un oggetto ResourceDictionary
.
L'esempio seguente illustra l'oggetto LightTheme
dell'applicazione di esempio:
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
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>
L'esempio seguente illustra l'oggetto DarkTheme
dell'applicazione di esempio:
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
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>
Ogni ResourceDictionary
contiene Color
risorse che definiscono i rispettivi temi, ognuna ResourceDictionary
con valori di chiave identici. Per altre informazioni sui dizionari risorse, vedere Dizionari risorse.
Importante
Per ogni ResourceDictionary
oggetto è necessario un file code-behind che chiama il InitializeComponent
metodo . Questa operazione è necessaria in modo che sia possibile creare un oggetto CLR che rappresenta il tema scelto in fase di esecuzione.
Impostare un tema predefinito
Un'applicazione richiede un tema predefinito, in modo che i controlli abbiano valori per le risorse utilizzate. È possibile impostare un tema predefinito unendo il tema a livello ResourceDictionary
di ResourceDictionary
applicazione definito in App.xaml:
<Application xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ThemingDemo.App">
<Application.Resources>
<ResourceDictionary Source="Themes/LightTheme.xaml" />
</Application.Resources>
</Application>
Per altre informazioni sull'unione di dizionari risorse, vedere Dizionari risorse uniti.
Utilizzare le risorse del tema
Quando un'applicazione vuole utilizzare una risorsa archiviata in un ResourceDictionary
oggetto che rappresenta un tema, deve farlo con l'estensione DynamicResource
di markup. In questo modo si garantisce che, se in fase di esecuzione è selezionato un tema diverso, verranno applicati i valori del nuovo tema.
L'esempio seguente illustra tre stili dell'applicazione di esempio che possono essere applicati agli Label
oggetti :
<Application xmlns="http://xamarin.com/schemas/2014/forms"
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>
Questi stili vengono definiti nel dizionario risorse a livello di applicazione, in modo che possano essere utilizzati da più pagine. Ogni stile utilizza le risorse del tema con l'estensione di DynamicResource
markup.
Questi stili vengono quindi utilizzati dalle pagine:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
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>
Quando una risorsa del tema viene utilizzata direttamente, deve essere utilizzata con l'estensione di DynamicResource
markup. Tuttavia, quando viene utilizzato uno stile che usa l'estensione DynamicResource
di markup, deve essere utilizzato con l'estensione di StaticResource
markup.
Per altre informazioni sullo stile, vedi Applicazione Xamarin.Forms di stili alle app con stili XAML. Per altre informazioni sull'estensione DynamicResource
di markup, vedere Stili dinamici in Xamarin.Forms.
Caricare un tema in fase di esecuzione
Quando un tema viene selezionato in fase di esecuzione, l'applicazione deve:
- Rimuovere il tema corrente dall'applicazione. Questa operazione viene ottenuta cancellando la
MergedDictionaries
proprietà a livelloResourceDictionary
di applicazione . - Caricare il tema selezionato. A tale scopo, aggiungere un'istanza del tema selezionato alla
MergedDictionaries
proprietà del livelloResourceDictionary
applicazione .
Tutti VisualElement
gli oggetti che impostano le proprietà con l'estensione DynamicResource
di markup applicheranno quindi i nuovi valori del tema. Ciò si verifica perché l'estensione DynamicResource
di markup gestisce un collegamento alle chiavi del dizionario. Pertanto, quando i valori associati alle chiavi vengono sostituiti, le modifiche vengono applicate agli VisualElement
oggetti .
Nell'applicazione di esempio viene selezionato un tema tramite una pagina modale che contiene un oggetto Picker
. Il codice seguente mostra il OnPickerSelectionChanged
metodo , che viene eseguito quando cambia il tema selezionato:
void OnPickerSelectionChanged(object sender, EventArgs e)
{
Picker picker = sender as Picker;
Theme theme = (Theme)picker.SelectedItem;
ICollection<ResourceDictionary> mergedDictionaries = Application.Current.Resources.MergedDictionaries;
if (mergedDictionaries != null)
{
mergedDictionaries.Clear();
switch (theme)
{
case Theme.Dark:
mergedDictionaries.Add(new DarkTheme());
break;
case Theme.Light:
default:
mergedDictionaries.Add(new LightTheme());
break;
}
}
}