장난감 연구소

[UWP] UWP 앱 색상 모드 지원하기 본문

개발/UWP

[UWP] UWP 앱 색상 모드 지원하기

changi1122 2019. 11. 26. 17:21
    728x90

    이 글에서는 UWP 앱에서 라이트 모드(밝게), 다크 모드(어둡게)를 고정 적용하거나 시스템 설정을 따르는 방법, 앱 내의 설정에서 색상 모드를 설정할 수 있게 하는 방법, 색상 모드에 따라 색이 변하는 ThemeResource에 대해 다룬다.

    색상 모드 고정 또는 시스템 설정 적용

    <!-- App.xaml -->
    <Application
        x:Class="ThemeTestApp.App"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:ThemeTestApp"
        RequestedTheme="(Light or Dark)">
    </Application>

    색상모드 고정

    App.xaml 파일에서 UWP 앱의 색상 모드를 설정할 수 있다. 시스템 설정에 상관없이 라이트 모드 또는 다크 모드로 고정하고 싶다면 App.xaml 파일의 Application 태그에 RequestedTheme 속성을 주면 된다. RequestedTheme="Light"로 설정하면 라이트 모드, RequestedTheme="Dark"로 설정하면 다크 모드로 고정된다.

    시스템 설정 적용

    Visual Studio를 이용하여 UWP 앱 프로젝트를 생성하였을 때, 기본 값은 시스템 설정을 따르는 것이다. 만약 설정 앱>개인 설정>색>기본 앱 모드 선택에서 '밝게' 또는 '어둡게'로 변경하였는데도 적용되지 않는다면, 한 색상 모드로 설정되어 있을 수도 있다. App.xaml 파일에서 Application 태그의 RequestedTheme 속성이 지정되어있다면 지우면 된다.

    앱 내 설정에서 색상 모드 선택

    '날씨' 앱

    경우에 따라서는 앱 사용자가 색상 모드를 선택하도록 개발할 수도 있다. 예를 들어 윈도우 10의 '날씨' 앱은 설정에서 앱의 색상모드를 '밝게', '어둡게', 'Windows 기본값'으로 선택할 수 있다. 이와 같은 기능을 만들기 위해서는 앱 내 설정에서 색상 모드를 선택한 것을 저장하고, 앱이 실행될 때 저장된 값을 불러와 RequestedTheme를 설정해야 한다.

    선택한 색상 모드 저장 (MainPage.xaml)

    위 사진처럼 라디오 버튼을 사용하여 만들어 보자. 글의 맨 아래에 예시 프로젝트를 첨부하였다.

    <!-- MainPage.xaml -->
    <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
        <TextBlock Text="모드 선택" FontSize="16" />
        <RadioButton x:Name="RbLight" GroupName="ColorMod" Content="밝게" Click="RbLight_Click"/>
        <RadioButton x:Name="RbDark" GroupName="ColorMod" Content="어둡게" Click="RbDark_Click"/>
        <RadioButton x:Name="RbSystem" GroupName="ColorMod" Content="Windows 기본값" Click="RbSystem_Click"/>
    </StackPanel>

    MainPage.xaml은 이렇다. 3개의 라디오 버튼을 클릭하였을 때 클릭 이벤트에 따라 메소드가 실행된다.

    // MainPage.xaml
    private void RbLight_Click(object sender, RoutedEventArgs e)
    {
        Windows.Storage.ApplicationDataContainer localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
        localSettings.Values["#ColorTheme"] = "Light";
    }
    
    private void RbDark_Click(object sender, RoutedEventArgs e)
    {
        Windows.Storage.ApplicationDataContainer localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
        localSettings.Values["#ColorTheme"] = "Dark";
    }
    
    private void RbSystem_Click(object sender, RoutedEventArgs e)
    {
        Windows.Storage.ApplicationDataContainer localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
        localSettings.Values["#ColorTheme"] = "System";
    }

    MainPage.xaml.cs를 위와 같이 구현하였다. 앱의 설정을 저장하기 위해서 ApplicationDataContainer 클래스를 사용할 수 있다. 이제 앱이 실행될 때 저장된 문자열에 맞게 RequestedTheme가 설정되도록 해야 한다.

    RequestedTheme 설정 (App.xaml.cs)

    // App.xaml.cs
    public App()
    {
        // Color Theme
        Windows.Storage.ApplicationDataContainer localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
        string colorTheme = (string)localSettings.Values["#ColorTheme"];
        if (colorTheme != null)
        {
            if (colorTheme == "Light")
                RequestedTheme = ApplicationTheme.Light;
            else if (colorTheme == "Dark")
                RequestedTheme = ApplicationTheme.Dark;
        }
    
        this.InitializeComponent();
        this.Suspending += OnSuspending;
    }

    App.xaml.cs에서 this.InitializeComponent(); 위에 저장된 문자열을 불러오고, RequestedTheme를 설정하는 코드를 넣었다. 이때 Values["#ColorTheme"]로 저장된 값이 없으면 null이다. 그래서 if 문으로 colorTheme가 null이 아닌 경우만 코드를 실행하도록 하였다.

    RequestedTheme를 설정하지 않으면 자동으로 시스템 설정을 따라가기 때문에 "System"에 대해서는 어떠한 코드도 넣지 않았다. 라디오 버튼으로 설정한 경우 앱을 다시 실행할 때 적용된다.

    색상 모드에 따라 색이 변하는 리소스

    UWP에서 제공하는 대부분의 XAML 컨트롤은 자동으로 각 색상 모드에 맞춰 색이 변한다. 그런데 디자인에 따라서는 직접 색상을 정해줘야 할 때도 있다. 이럴 때는 Application.Resources나 Page.Resource에서 ThemeResource를 정의하고, 사용하면 된다.

    예시 프로젝트를 다시 살펴보자. 예시로 App.xaml에 아래와 같이 ThemeResource를 정의해놓았다. 예를 들어 컨트롤의 배경으로 GridBackgroundBrush를 사용하면, Light Theme일 때는 #F3F3F3이 적용되고, Dark Theme일 때는 #202020이 적용된다.

    리소스는 SolidColorBrush 이외에도 Style이나 x:String을 정의하고 사용할 수도 있다.

     <!-- App.xaml -->
     <Application>
       <Application.Resources>
          <ResourceDictionary>
            <ResourceDictionary.ThemeDictionaries>
              <ResourceDictionary x:Key="Light">
                <x:String x:Key="Mode">Light Mode</x:String>
                <SolidColorBrush x:Key="GridBackgroundBrush" Color="#F3F3F3"/>
                <SolidColorBrush x:Key="GridBorderBrush" Color="#E5E5E5"/>
              </ResourceDictionary>
              <ResourceDictionary x:Key="Dark">
                <x:String x:Key="Mode">Dark Mode</x:String>
                <SolidColorBrush x:Key="GridBackgroundBrush" Color="#202020"/>
                <SolidColorBrush x:Key="GridBorderBrush" Color="#1D1D1D"/>
              </ResourceDictionary>
            </ResourceDictionary.ThemeDictionaries>
          </ResourceDictionary>
      </Application.Resources>
    </Application>

    XAML과 C#에서 리소스를 사용할 때는 각각 아래와 같이 ThemeResource를 사용할 수 있다.

    // XAML (MainPage.xaml)
    <Grid Background="{ThemeResource GridBackgroundBrush}"
          BorderBrush="{ThemeResource GridBorderBrush}">
        <TextBlock Text="{ThemeResource Mode}"></TextBlock>
    </Grid>
    // C#
    
    // Application.Resource에 정의한 경우
    SolidColorBrush background = Application.Current.Resources["GridBackgroundBrush"] as SolidColorBrush;
    // Page.Resource에 정의한 경우 (해당 페이지 클래스 안에서)
    SolidColorBrush background = this.Resources["GridBackgroundBrush"] as SolidColorBrush;

     

    Grid에 ThemeResource를 적용한 결과 사진
    Grid에 ThemeResource를 적용한 결과

     

    코드에서 현재 색상 모드 확인하기

    C# 코드에서 현재 앱의 색상 모드를 확인하려면 아래와 같은 코드를 사용하면 된다.

    if (App.Current.RequestedTheme == ApplicationTheme.Light) {
    }
    else if (App.Current.RequestTheme == ApplicationTheme.Dark) {
    }

     

    예시 소스코드

    ColorTheme.zip
    0.53MB