Xamarin.Forms 應用程式可以使用標記延伸,在運行 DynamicResource 時間動態響應樣式變更。 這個標記延伸類似於 StaticResource 標記延伸,這兩者都使用字典索引鍵從 ResourceDictionary擷取值。 不過,當標記延伸執行單一字典查閱時 StaticResource , DynamicResource 標記延伸會維護字典索引鍵的連結。 因此,如果已取代與索引鍵相關聯的值,則會將變更套用至 VisualElement。 這可讓運行時間主題在應用程式中實作 Xamarin.Forms 。
在應用程式中實作執行時間主題 Xamarin.Forms 的程式如下:
- 定義 中
ResourceDictionary每個主題的資源。 - 使用標記延伸,取用
DynamicResource應用程式中的主題資源。 - 在應用程式的 App.xaml 檔案中設定預設主題。
- 新增程式代碼以在運行時間載入主題。
重要
StaticResource如果您不需要在運行時間變更應用程式主題,請使用標記延伸。
下列螢幕快照顯示主題頁面,其中 iOS 應用程式使用淺色主題和 Android 應用程式使用深色主題:
注意
在運行時間變更主題需要使用 XAML 樣式,而且目前無法使用 CSS。
定義主題
主題定義為儲存在中的 ResourceDictionary資源物件集合。
下列範例顯示 LightTheme 來自範例應用程式的 :
<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>
下列範例顯示 DarkTheme 來自範例應用程式的 :
<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>
每個 ResourceDictionary 都包含 Color 定義其個別主題的資源,且每個資源都 ResourceDictionary 使用相同的索引鍵值。 如需資源字典的詳細資訊,請參閱 資源字典。
重要
每個 ResourceDictionary都需要檔案後置程序代碼,其會呼叫 InitializeComponent 方法。 這是必要的,如此一來,就可以在運行時間建立代表所選主題的CLR物件。
設定預設主題
應用程式需要默認主題,讓控件具有其取用資源的值。 您可以將主題ResourceDictionary合併為 App.xaml 中定義的應用程式層級ResourceDictionary,以設定預設主題:
<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>
如需合併資源字典的詳細資訊,請參閱 合併的資源字典。
取用主題資源
當應用程式想要取用儲存在 代表主題之 中的 ResourceDictionary 資源時,應該使用 DynamicResource 標記延伸來執行此動作。 這可確保如果在運行時間選取不同的主題,則會套用新主題中的值。
下列範例顯示可套用至 Label 物件的範例應用程式中的三種樣式:
<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>
這些樣式定義在應用層級資源字典中,以便可供多個頁面取用。 每個樣式都會使用 DynamicResource 標記延伸的主題資源。
這些樣式接著會由頁面取用:
<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>
直接取用主題資源時,應該使用標記延伸來取用 DynamicResource 。 不過,當使用標記延伸的DynamicResource樣式使用時,應該使用標記延伸。StaticResource
如需樣式的詳細資訊,請參閱 使用 XAML 樣式設定 Xamarin.Forms 應用程式樣式。 如需標記延伸的詳細資訊 DynamicResource ,請參閱 中的 Xamarin.Forms動態樣式。
在運行時間載入主題
在執行時間選取主題時,應用程式應該:
- 從應用程式移除目前的主題。 這可藉由清除
MergedDictionaries應用層級ResourceDictionary的屬性來達成。 - 載入選取的主題。 這可藉由將所選主題的實例新增至
MergedDictionaries應用層級ResourceDictionary的屬性來達成。
任何 VisualElement 使用 DynamicResource 標記延伸設定屬性的對象,都會套用新的主題值。 這是因為 DynamicResource 標記延伸會維護字典索引鍵的連結。 因此,當取代與索引鍵相關聯的值時,這些變更會套用至 VisualElement 物件。
在範例應用程式中,會透過包含 Picker的強制回應頁面選取主題。 下列程式代碼顯示 OnPickerSelectionChanged 方法,這個方法會在選取的主題變更時執行:
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;
}
}
}

