【Power Apps】テーマカラー変更機能を実装しよう

:::note warn
本記事の実装をより改良した記事をアップしておりますので、
ぜひこちらをご参考にしていただければと思います。
:::
https://qiita.com/reire/items/277118cf4f3507e6fd13

# はじめに
こんにちは、reireです。

ダークモード機能やテーマカラー変更機能ってありますよね。
無いならないで良いけど、あったらﾁｮｯﾄﾘｯﾁでﾁｮｯﾄｳﾚｼｲそんな機能。

今となってはいろんなアプリやWebサイト、OSにも搭載されています。

今回は、そういった機能をPower Appsにさくっと実装してみようというお話です。

# 動作イメージ

何事も結果や結論から話すべし。
本記事では以下のような動作を実装していくイメージです。

<img width="750" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3461887/8de5069a-a0cc-c581-32ff-c4aa54a0c607.gif"></img>

# 機能要件

ざっくり以下の機能を実装していく。

- 設定ボタンをクリックすると変更できるテーマカラーが一覧で表示される
- 一覧の中から任意のカラーを選択するとアプリ全体のテーマカラーが変わる
- 選択したテーマカラーは同一端末で次回アプリを起動する際にも引き継がれる

# さっそく実装

## 1. まずはアプリの画面を作成

今回の本題はアプリ自体ではないので、手っ取り早くテンプレートのカレンダーに実装していきます。
皆さんはそれぞれ既存や新規のアプリ画面をご用意ください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3461887/d478b91b-23e9-53e3-6f79-4ca81cecdcf6.png)

## 2. App.OnStartを設定

アプリ起動時の処理になります。
このタイミングでアプリに実装する各テーマセットの初期化をしていきます。

```App.OnStart

//各テーマを定義
Concurrent(
    ClearCollect(
        nomal_theme,
        {
            base:RGBA(255,190,90,1),
            hover:RGBA(255,214,112,1),
            select:RGBA(255,214,152, 50%),
            press:RGBA(242,174,73,1)
        }
    );,
    ClearCollect(
        dark_theme,
        {
            base:RGBA(80,80,80,1),
            hover:RGBA(180,180,180,1),
            select:RGBA(255,214,152, 50%),
            press:RGBA(55,55,55,1)
        }
    );,
    ClearCollect(
        blue_theme,
        {
            base:RGBA(28,46,92,1),
            hover:RGBA(109,133,178,1),
            select:RGBA(109,133,178, 30%),
            press:RGBA(20,35,80,1)
        }
    );
);

//Sub_themeに各テーマを適用
ClearCollect(Sub_theme,nomal_theme,dark_theme,blue_theme);

//ユーザーのローカルデータ読み込み
LoadData(tmp_main_theme,"Local_main_theme",false);,

//ローカルデータの存在チェック
If(Not(IsEmpty(Local_main_theme)),
    //存在する場合はメインテーマをローカルから適用。(前回起動時のデータが引き継がれる。)
    ClearCollect(Main_theme,First(Local_main_theme));,
    //存在しなければnomal_themeを適用する。
    ClearCollect(Main_theme,nomal_theme);,
);

//サブテーマからメインテーマを削除
Remove(Sub_theme,Main_theme);

//後でテーマ一覧タブの操作に使用するので先に宣言しておく
UpdateContext({conf_tab:false});

```

> - 選択したテーマカラーは同一端末で次回アプリを起動する際にも引き継がれる

こちらを実現するために「**LoadData関数**」と「**SaveData関数**(後で登場)」を使用しています。
ユーザーのローカルデータに選択しているテーマとその他のテーマを保存しておくことで、次回起動時も前回選択したテーマカラーを引き継ぐことができます。

:::note warn
ちなみにこの段階だと記述したコードにエラーが見つかりますが無視でOK
:::

そしてテーマはコレクション形式で定義しています。
各テーマごとにベースカラーや各アクションやオブジェクト用のカラーをRGBA形式で定義しまとめています。

それらの各テーマを
- 現在ユーザーが選択しているMain_theme
- ユーザーが選択していないSub_theme

に振り分けています。

:::note info
App.OnStartに記述ができたタイミングで「OnStartを実行する」をしておくと後がスムーズです。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3461887/d38709ae-ce1e-c243-5915-c821f26f7a3f.png"></img>
:::

## 3. テーマ変更用の各種オブジェクトを作成

> - 設定ボタンをクリックすると変更できるテーマカラーが一覧で表示される

というわけで設定ボタンとタブとしてコンテナ、さらにその配下に一覧表示のためにギャラリーを配置していく。

↓見た目とツリービュー
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3461887/cea3272e-5691-4997-30a1-9c8b4717f5c1.png"></img>

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3461887/86067fb4-8209-359f-c150-91b54edbfa66.png"></img>
配置する箇所やサイズ、構成などは皆さんのアプリに合わせてよしなに調整してください。

そしてテーマ一覧タブの表示、非表示の処理を記述

```Theme_Icon.OnSelect
UpdateContext({conf_tab:!conf_tab});
```

```Theme_Tab.Visible
conf_tab
```
:::note info
bool値は否定演算子をつけて再宣言すればIf関数などで判定しなくても反転できる
:::

続けて本命のテーマ入れ替え処理

```Theme_Gallery.Items
Sub_theme
```

```Theme_Button.Fill
ThisItem.base
```

```Theme_Button.OnSelect
//選択したテーマをMain_themeに定義し、サブテーマからは削除
Collect(Sub_theme,First(Main_theme));
ClearCollect(Main_theme,ThisItem);
Remove(Sub_theme,ThisItem);

ClearData("Local_main_theme");

//現在のテーマの選択状況をローカルデータに保存
SaveData(First(Main_theme),"Local_main_theme");
```

この時点で「App.OnStartを実行する」を済ませていると
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3461887/ffa3a187-f860-1222-43a3-8e19e3931616.png"></img>
この通りTheme_ButtonのFillに、Sub_theme内の各テーマのbaseカラーが設定される。
(まだであればこのタイミングでApp.OnStartを実行しておきましょう。)

これにより変更できるテーマのメインカラーをユーザーへシンプルに伝えることができる。

そしてTheme_Buttonをクリックすると、
現在のMain_themeと選択したSub_themeを入れ替えてその状態をSaveDataされる。
これで各テーマの適用状態が保存され次回起動時に参照することができる。

テーマカラー変更に関する処理は以上です。
案外簡単ですよね。

## 4. 各オブジェクトにテーマカラーを適用

ついにアプリの各オブジェクトにテーマカラーを適用していきます。
といっても方法はとても簡単。

各オブジェクトのFillやColorに対して
```〇〇.Fill
First(Main_theme).base #baseなど任意のパラメーターを指定
```

などを設定していくだけです。

場合によっては各オブジェクトに設定されているRGBA(,,,)と置換してしまうのが早いかもですね。

## 5. 動作確認

これらの設定を済ませることで…
<img width="750" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3461887/8de5069a-a0cc-c581-32ff-c4aa54a0c607.gif"></img>

自由自在にテーマカラーを変更することができますね！

もちろん定義するテーマカラーの数やパラメーターの種類を増やせば、
より豊富なテーマカラーと、アクションやオブジェクトごとにより詳細なカラーの設定が可能になります。

ちなみに今回載せているコードにはエラー処理などは特に考慮してませんので、皆さんのアプリに合わせて対処してください。

:::note warn
注意点としてエディター画面からのプレビュー再生では
「SaveData」、「LoadData」、「ClearData」辺りの関数が完全にはサポートされておらずエラーが出ます。(といっても見た目上動作はするけど。)
そのため気は進みませんが、動作確認はアプリ公開して実際に再生してみたほうがいいですね。
:::

# おわり
以上、Power Appsにおけるテーマカラー変更機能の実装でした。

中身はシンプルですが、こういう実装は画面が目に見えて変化するので結構楽しいですね。

本記事を参考に皆さんのアプリにも実装してみていただけると嬉しいです。

~~自作のアプリをダークモードにしてイキリ倒そうぜ！~~

それでは。