Xamarin Forms 응용 프로그램 테마Theming a Xamarin.Forms Application

샘플 다운로드 샘플 다운로드Download Sample Download the sample

Xamarin Forms 응용 프로그램은 DynamicResource 태그 확장을 사용 하 여 런타임에 동적으로 스타일 변경에 응답할 수 있습니다.Xamarin.Forms applications can respond to style changes dynamically at runtime by using the DynamicResource markup extension. 이 태그 확장은 둘 다 사전 키를 사용 하 여 ResourceDictionary에서 값을 인출 한다는 점에서 StaticResource 태그 확장과 비슷합니다.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. 그러면 Xamarin.ios 응용 프로그램에서 런타임 테마를 구현할 수 있습니다.This enables runtime theming to be implemented in Xamarin.Forms applications.

Xamarin.ios 응용 프로그램에서 런타임 테마를 구현 하는 프로세스는 다음과 같습니다.The process of implementing runtime theming in a Xamarin.Forms application is as follows:

  1. @No__t_1에서 각 테마에 대 한 리소스를 정의 합니다.Define the resources for each theme in a ResourceDictionary.
  2. @No__t_0 태그 확장을 사용 하 여 응용 프로그램의 테마 리소스를 사용 합니다.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.

다음 스크린샷은 테마 페이지를 표시 하며, 진한 테마를 사용 하 여 밝은 테마와 Android 응용 프로그램을 사용 하는 iOS 응용 프로그램입니다.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

테마 정의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.

중요

@No__t_1 메서드를 호출 하는 각 ResourceDictionary에 코드 숨김이 필요 합니다.A 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. 테마의 ResourceDictionaryapp.xaml에 정의 된 응용 프로그램 수준 ResourceDictionary에 병합 하 여 기본 테마를 설정할 수 있습니다.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.

다음 예제에서는 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.

스타일 지정에 대 한 자세한 내용은 XAML 스타일을 사용 하 여 Xamarin.ios 앱 스타일지정을 참조 하세요.For more information about styling, see Styling Xamarin.Forms Apps using XAML Styles. @No__t_0 태그 확장에 대 한 자세한 내용은 xamarin.ios의 동적 스타일(영문)을 참조 하세요.For more information about the DynamicResource markup extension, see Dynamic Styles in 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. 이렇게 하려면 응용 프로그램 수준 ResourceDictionaryMergedDictionaries 속성을 선택 취소 합니다.This is achieved by clearing the MergedDictionaries property of the application-level ResourceDictionary.
  2. 선택한 테마를 로드 합니다.Load the selected theme. 이렇게 하려면 선택한 테마의 인스턴스를 응용 프로그램 수준 ResourceDictionaryMergedDictionaries 속성에 추가 합니다.This is achieved by adding an instance of the selected theme to the MergedDictionaries property of the application-level ResourceDictionary.

@No__t_2 태그 확장을 사용 하 여 속성을 설정 하는 모든 VisualElement 개체는 새 테마 값을 적용 합니다.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;
        }
    }
}