アプリケーションのテーマを :::no-loc(Xamarin.Forms)::: 適用するTheme a :::no-loc(Xamarin.Forms)::: Application

サンプルのダウンロードサンプルのダウンロードDownload Sample Download the sample

:::no-loc(Xamarin.Forms)::: アプリケーションは、マークアップ拡張機能を使用して、実行時に動的にスタイル変更に応答でき DynamicResource ます。:::no-loc(Xamarin.Forms)::: applications can respond to style changes dynamically at runtime by using the DynamicResource markup extension. このマークアップ拡張機能は、 StaticResource マークアップ拡張機能に似ています。では、ディクショナリキーを使用してから値をフェッチし ResourceDictionary ます。This markup extension is similar to the StaticResource markup extension, in that both use a dictionary key to fetch a value from a ResourceDictionary. ただし、 StaticResource マークアップ拡張機能は、単一の辞書参照を実行しますが、 DynamicResource マークアップ拡張機能はディクショナリキーへのリンクを保持します。However, while the StaticResource markup extension performs a single dictionary lookup, the DynamicResource markup extension maintains a link to the dictionary key. このため、キーに関連付けられている値が置換された場合、変更はに適用され VisualElement ます。Therefore, if the value associated with the key is replaced, the change is applied to the VisualElement. これにより、アプリケーションでランタイムテーマを実装できるようになり :::no-loc(Xamarin.Forms)::: ます。This enables runtime theming to be implemented in :::no-loc(Xamarin.Forms)::: applications.

アプリケーションにランタイムテーマを実装するプロセス :::no-loc(Xamarin.Forms)::: は次のとおりです。The process for implementing runtime theming in a :::no-loc(Xamarin.Forms)::: application is as follows:

  1. 内の各テーマのリソースを定義 ResourceDictionary します。Define the resources for each theme in a ResourceDictionary.
  2. マークアップ拡張機能を使用して、アプリケーションでテーマリソースを使用し DynamicResource ます。Consume theme resources in the application, using the DynamicResource markup extension.
  3. アプリケーションの app.xaml ファイルに既定のテーマを設定します。Set a default theme in the application's App.xaml file.
  4. 実行時にテーマを読み込むコードを追加します。Add code to load a theme at runtime.

重要

StaticResource実行時にアプリのテーマを変更する必要がない場合は、マークアップ拡張機能を使用します。Use the StaticResource markup extension if you don't need to change the app theme at runtime.

次のスクリーンショットは、テーマが適用されたページを示しています。 iOS アプリケーションでは、明るいテーマと Android アプリケーションを使用して、ダークテーマを使用しています。The following screenshots show themed pages, with the iOS application using a light theme and the Android application using a dark theme:

IOS および Android でのテーマ付きアプリのメインページのスクリーンショット テーマが適用されたアプリの詳細ページのスクリーンショット (IOS と Android)Screenshot of the main page of a themed app, on iOS and Android Screenshot of the detail page of a themed app, on iOS and Android

注意

実行時にテーマを変更するには、XAML スタイルを使用する必要があります。現在、CSS を使用することはできません。Changing a theme at runtime requires the use of XAML styles, and is not currently possible using CSS.

テーマを定義するDefine themes

テーマは、に格納されているリソースオブジェクトのコレクションとして定義され ResourceDictionary ます。A theme is defined as a collection of resource objects stored in a ResourceDictionary.

次の例は、サンプルアプリケーションのを示してい LightTheme ます。The following example shows the LightTheme from the sample application:

<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 ます。The following example shows the DarkTheme from the sample application:

<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 同一のキー値を使用します。Each ResourceDictionary contains Color resources that define their respective themes, with each ResourceDictionary using identical key values. リソースディクショナリの詳細については、「 リソースディクショナリ」を参照してください。For more information about resource dictionaries, see Resource Dictionaries.

重要

メソッドを呼び出すそれぞれに、分離コードファイルが必要です ResourceDictionary InitializeComponentA code behind file is required for each ResourceDictionary, which calls the InitializeComponent method. これは、選択したテーマを表す CLR オブジェクトを実行時に作成できるようにするために必要です。This is necessary so that a CLR object representing the chosen theme can be created at runtime.

既定のテーマを設定するSet a default theme

アプリケーションには既定のテーマが必要であるため、コントロールには、使用するリソースの値を設定できます。An application requires a default theme, so that controls have values for the resources they consume. 既定のテーマを設定するには、 ResourceDictionary ResourceDictionary app.xaml に定義されているアプリケーションレベルにテーマをマージします。A default theme can be set by merging the theme's ResourceDictionary into the application-level ResourceDictionary that's defined 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>

リソースディクショナリのマージの詳細については、「マージされた リソースディクショナリ」を参照してください。For more information about merging resource dictionaries, see Merged resource dictionaries.

テーマリソースの使用Consume theme resources

テーマを表すに格納されているリソースをアプリケーションが使用する場合は、 ResourceDictionary マークアップ拡張機能を使用して実行する必要があり DynamicResource ます。When an application wants to consume a resource that's stored in a ResourceDictionary that represents a theme, it should do so with the DynamicResource markup extension. これにより、実行時に別のテーマが選択された場合に、新しいテーマの値が適用されるようになります。This ensures that if a different theme is selected at runtime, the values from the new theme will be applied.

次の例は、オブジェクトに適用できるサンプルアプリケーションの3つのスタイルを示してい Label ます。The following example shows three styles from the sample application that can be applied to Label objects:

<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>

これらのスタイルは、アプリケーションレベルのリソースディクショナリで定義されているので、複数のページで使用できます。These styles are defined in the application-level resource dictionary, so that they can be consumed by multiple pages. 各スタイルは、マークアップ拡張機能を使用してテーマリソースを使用 DynamicResource します。Each style consumes theme resources with the DynamicResource markup extension.

これらのスタイルは、次のページによって使用されます。These styles are then consumed by pages:

<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="  &#x2022; Cynical but not unfriendly."
                       Style="{StaticResource SmallLabelStyle}" />
                <Label Text="  &#x2022; Seven varieties of grimaces."
                       Style="{StaticResource SmallLabelStyle}" />
                <Label Text="  &#x2022; Doesn't laugh at your jokes."
                       Style="{StaticResource SmallLabelStyle}" />
            </StackLayout>
            ...
        </Grid>
    </ScrollView>
</ContentPage>

テーマリソースを直接使用する場合は、マークアップ拡張機能で使用する必要があり DynamicResource ます。When a theme resource is consumed directly, it should be consumed with the DynamicResource markup extension. ただし、 DynamicResource マークアップ拡張機能を使用するスタイルが使用されている場合は、 StaticResource マークアップ拡張機能で使用する必要があります。However, when a style that uses the DynamicResource markup extension is consumed, it should be consumed with the StaticResource markup extension.

スタイル設定の詳細については、「 :::no-loc(Xamarin.Forms)::: XAML スタイルを使用したアプリのスタイル設定」を参照してください。For more information about styling, see Styling :::no-loc(Xamarin.Forms)::: Apps using XAML Styles. マークアップ拡張機能の詳細については DynamicResource 、「 」 :::no-loc(Xamarin.Forms)::: の「動的スタイル」を参照してください。For more information about the DynamicResource markup extension, see Dynamic Styles in :::no-loc(Xamarin.Forms):::.

実行時にテーマを読み込むLoad a theme at runtime

実行時にテーマを選択すると、アプリケーションは次のことを行う必要があります。When a theme is selected at runtime, the application should:

  1. 現在のテーマをアプリケーションから削除します。Remove the current theme from the application. これは MergedDictionaries 、アプリケーションレベルのプロパティをクリアすることで実現され ResourceDictionary ます。This is achieved by clearing the MergedDictionaries property of the application-level ResourceDictionary.
  2. 選択したテーマを読み込みます。Load the selected theme. これを実現するには、選択したテーマのインスタンスを MergedDictionaries アプリケーションレベルのプロパティに追加し ResourceDictionary ます。This is achieved by adding an instance of the selected theme to the MergedDictionaries property of the application-level ResourceDictionary.

VisualElementマークアップ拡張機能を使用してプロパティを設定するすべてのオブジェクトで、 DynamicResource 新しいテーマの値が適用されます。Any VisualElement objects that set properties with the DynamicResource markup extension will then apply the new theme values. これは、 DynamicResource マークアップ拡張機能がディクショナリキーへのリンクを保持しているために発生します。This occurs because the DynamicResource markup extension maintains a link to dictionary keys. そのため、キーに関連付けられている値が置換されると、その変更がオブジェクトに適用され VisualElement ます。Therefore, when the values associated with keys are replaced, the changes are applied to the VisualElement objects.

サンプルアプリケーションでは、を含むモーダルページを使用してテーマを選択し Picker ます。In the sample application, a theme is selected via a modal page that contains a Picker. 次のコードは、 OnPickerSelectionChanged 選択したテーマが変更されたときに実行されるメソッドを示しています。The following code shows the OnPickerSelectionChanged method, which is executed when the selected theme changes:

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;
        }
    }
}