tmytのらくがき

個人の日記レベルです

Uno PlatformでDarkテーマを使うにはPre-releaseにする

Uno CalculatorがDark modeをサポートしたよ!っていうアップデートが配信されていたのでソースを読みながら同じようにしてもDarkにならんのやが…って1日考えてみた結果、Pre-releaseにしたら解決しました。という話です。

ThemeDictionariesが動かない

例えばこんな感じで書くと2019年12月2日現在のリリース版のUno Platformだと動きません。

<Application
    x:Class="UnoApp2.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Application.Resources>
    <ResourceDictionary>
      <ResourceDictionary.ThemeDictionaries>
        <ResourceDictionary x:Key="Default">
          <SolidColorBrush x:Key="ThemeBrush" Color="DarkBlue" />
          <SolidColorBrush x:Key="BackgroundBrush" Color="Gray" />
        </ResourceDictionary>
        <ResourceDictionary x:Key="Light">
          <SolidColorBrush x:Key="ThemeBrush" Color="Red" />
          <SolidColorBrush x:Key="BackgroundBrush" Color="#ccccff" />
        </ResourceDictionary>
      </ResourceDictionary.ThemeDictionaries>
    </ResourceDictionary>
  </Application.Resources>
</Application>

これは、前にも話題にしたインラインなResourceDictionaryの動作に制限があるためで、ThemeDictionaries内のResourceDictionaryは解釈されません。

ただ、あくまでもインラインなResourceDictionaryが問題なのであって以前に話題に挙げたようにglobal-level*1な ResourceDictionaryに定義すれば2019年12月2日現時点のリリース版でもThemeDictionariesの中身は解釈されます。 ただ、この場合常にテーマはLightとして処理されます。

ThemeDictionariesは動く

ThemeDictionariesは動きます。ただUno.UIのPre-Release版が必要です。

しつこいようですが2019年12月2日現在のリリース版は2019年7月23日にリリースされた1.45.0というバージョンが最新です。 このバージョンではThemeDictionariesを解釈することはできるのですが、DarkやHighContractを使用することはできません。

Light以外のテーマを使えるようになるには、2019年10月9日にマージされた#1628というプルリクエストを含んだバージョンにする必要があります。 これが一体どのバージョンからなのか…というのは探すのが大変なのであきらめました…

対応してるバージョンの境目を探すのも大変なので、とりあえず今回はUno.UIを2.1.0-dev.52というバージョンにNuGetから更新します。 このバージョンはプレリリース版としてマークされているので、NuGetの画面からプレリリースを含めるというところにチェックを付けると表示されます。

f:id:tmyt:20191202012036p:plain

Uno.UI以外はプロジェクトが生成されたときのデフォルトのままのバージョンを使ってビルドしても正しく動いているようです。

Uno.UIがプレリリース版に更新できたので、次のXAMLを適当な場所に保存します。ここではThemes/Styles.xamlという名前で保存しました。

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

  <ResourceDictionary.ThemeDictionaries>
    <ResourceDictionary x:Key="Default">
      <SolidColorBrush x:Key="ForegroundBrush" Color="DarkBlue" />
      <SolidColorBrush x:Key="BackgroundBrush" Color="Gray" />
    </ResourceDictionary>
    <ResourceDictionary x:Key="Light">
      <SolidColorBrush x:Key="ForegroundBrush" Color="Red" />
      <SolidColorBrush x:Key="BackgroundBrush" Color="#ccccff" />
    </ResourceDictionary>
  </ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>

これを使用するMainPage.xamlを次の内容で作成しました。

<Page
    x:Class="UnoApp2.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

  <Grid Background="{ThemeResource BackgroundBrush}">
    <TextBlock Foreground="{ThemeResource ForegroundBrush}" Text="Hello, world !" Margin="20" FontSize="30" />
  </Grid>
</Page>

App.xamlにはUWPとUnoの互換性の都合でMergedDictionariesの設定を書いてあります。

<Application
    x:Class="UnoApp2.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Application.Resources>
      <ResourceDictionary>
          <ResourceDictionary.MergedDictionaries>
              <ResourceDictionary  Source="Themes/Styles.xaml" />
          </ResourceDictionary.MergedDictionaries>
      </ResourceDictionary>
  </Application.Resources>
</Application>

ここまでをビルドして実行すると次の結果になります。期待した通りの結果ですね。

f:id:tmyt:20191202011938p:plain

ただ、Unoのテーマ実装ではまだ動的なテーマ変更に対応していません。おそらく#1766がマージされた日にはいろいろと解決するのでしょう…

github.com

*1:ルート要素がResourceDictionaryとなってるXAMLファイルをこう呼んでいるようです