PowerAppsでレスポンシブなアプリを作る

# PowerAppsでレスポンシブしたい！
本稿はPowerAppsでレスポブ対応アプリを作るときに必要な基本的なことをチートシート的にまとめたものです。
ベストプラクティスではないかもしれないので、もっといい方法があれば教えてください。

# まずはアプリの設定を変えておきましょう
これをしておかないと何も始まりません。
アプリの設定から、[画面とサイズの向き] - [詳細設定]の項目を全てオフにしておきます。
<img width="763" alt="AppSettings.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243135/4891ec60-8312-cb85-9a9b-c7abf3ac0593.png">
ついでに「数式バーの結果ビュー」も有効化しておいてもいいかもしれませんね。何かと便利なので笑

# PowerApps上の座標に関する前提知識
アプリをレスポブ対応させる前に、座標の考え方を押さえておきましょう。
知ってるわ！って人は読み飛ばしてください。(´・ω・`)

### アプリの横幅と縦幅に関して
レスポンシブに対応させると言うことは、アプリが使用される環境によって横幅や縦幅（ピクセル数）が変化するということです。このため、アプリ内で画面幅を動的に取得する必要があります。これらは、次のプロパティで取得することが出来ます。

```text:横幅
App.Width
```

```text:縦幅
App.Height
```

これらのプロパティ値は画面サイズの変化に応じて動的に変化するので、基本的にはこの値から計算してコントロールサイズを指定したり、場所を指定したりします。

### コントロールに指定するX・Y プロパティに関して
PowerAppsのコントロールにはそれぞれ X・Y というプロパティがあり、これを指定することでコントロールの表示位置（座標）を指定することができます。

ちなみに、(x, y) = (0, 0) の座標位置はアプリの左上隅の場所を示します。
つまり、Xに30を指定している場合は、左端から30ピクセルの位置を示すことになり、Yの場合も上端からの位置を示します。

じゃあ、アプリの右端や下端は？
  
これは、先程の画面サイズでご紹介した`App.Width` `App.Height`がそれぞれ同等の値になります。
右端の座標 = アプリの画面幅 = `App.Width`
下端の座標 = アプリの画面の高さ = `App.Height`
みたいな感じでしょうか。

そして、コントロールの X・Y プロパティに指定された値は、実際にはコントロールの左上端の位置を示すことになります。

上記をまとめて図にすると以下のようなイメージです。
![座標.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243135/941ebbca-20f6-86d4-774e-cff0dbd76060.png)

# コントロールのサイズを指定する
いよいよアプリをレスポンシブにしていきます！

まずはコントロールのサイズ指定です。

レスポブ対応させるアプリでは、コントロールの高さ・幅を**動的に指定**しておく必要があります。
例えば、画面幅の80%、画面の高さの10%と言った具合です。

この様に動的に指定せず、例えば`Width = 1000`で固定値を指定したとしましょう。
そうすると、PCやタブレットのような横幅が確保できる端末では問題ないですが、スマホなどの横幅の少ない端末では横スクロールが発生します。画面幅に対して動的に指定しておけば、これを回避できます。

このためには、コントロールのWidth・Heightプロパティを次のように指定してあげます。

```text:Width
App.Width * 0.8
```

```text:Height
App.Height * 0.1
```

単純ですね！画面幅や高さに対して割合を掛け算しているだけです。
この例では、コントロールは画面幅に対して80%の幅と画面の高さに対して10%の高さになります。
こうしておくことで画面の大きさに対してレスポンシブなサイズの指定ができました。

ただ、実際に利用するシーンを考えると、縦スクロールは特に苦にならないので、`Height`に関しては固定値でも問題ない気がしますね。

# コントロールの位置を指定する
レスポンシブでやっかいなのはココからです。コントロールのサイズは画面サイズに対する割合で指定できるので割と単純でした。
しかし、位置に関しては画面サイズに対して、座標を考慮しなければいけません。

例えば、コントロールを画面の中央にセンタリングしたいとします。
この場合、単純にプロパティ X に画面幅の半分 = `App.Width * 0.5`とか`App.Width / 2`とかを指定してもだめです。

コントロールの座標(x, y)はコントロールの左上端の位置を示すということを思い出してください。
このため、上記のように指定するとコントロールの左端がちょうどアプリの中心に来てしまいます。

こんな感じ。
![ControlCenteringMiss.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243135/b4c6fa91-977a-f468-4222-dcaca3ecb4f4.png)

**どうすればいいの？**
ってなりますよね。なんか数学が得意な人とかなら簡単に分かるんでしょうけど、私はそうではないので最初？？状態でした。
この場合、コントロールが目的の位置よりどれだけ右にずれているかを考えればよいです。

本来であれば、コントロールの中心がアプリの中心に来てほしいです。
ですが、今の状態だとアプリの中心よりも**コントロールの横幅の半分**だけ右にずれています。

なので、その分左にずらしてあげれば良いです。
コントロールの横幅は`コントロール名.Width`で取得出来ます。

まとめると、センタリングしたい場合は、コントロールのX座標に

```text:X
(App.Width / 2) - (コントロール名.Widht / 2)
```
を指定してあげればよいです。

Height指定をする際も同様で、

```text:Y
(App.Height / 2) - (コントロール名.Height / 2)
```
を指定してあげれば縦方向のセンタリングができます。

また、コントロールの座標において右端、下端の座標が分かればもう少しレスポブっぽい位置指定ができるようになります。
例えば、
- コントロールAの右端から30ピクセル右隣に配置する
- コントロールAの下端から15ピクセル下に配置する
のような指定が可能です。

このためには右端と下端の座標が必要です。
コントロールの座標は左上端を示すので、この値にそれぞれコントロールの幅と高さを足してあげれば右端と下端が計算できますね。

```text:右端の座標
コントロール名.X + コントロール名.Width
```

```text:下端の座標
コントロール名.Y + コントロール名.Height
```

みたいな感じですかね！
これらを上手く使ってあげると、ある特定のコントロールを元にその他のコントロールの位置を指定する相対レイアウトが実現できます。
（Androidアプリの開発経験がある方なら馴染み深い言葉ではないでしょうか、RelativeLayout 笑）

まとめて図にするとこんなイメージです。
![ControlArrangement.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243135/dbe0af1c-037e-8b97-87c4-a11d6222e016.png)

# 画面幅によって表示倍率を動的に可変させる。
基本的には上記の内容で対応出来るかと思いますが、実際に作ってみてPCやスマホで見比べると意外と思ったように表示されません。
そんな時はもう少し踏み込んで、画面の幅によって表示倍率を変えるということをやってみます。

いわゆるCSSのメディアクエリと同じ考え方ですね。
If()で一定の画面幅以下（もしくは以上）だったら、というような指定をします。

以下は画面幅が800px未満だったら90%の幅で、以上である場合は70%の幅で表示するという指定です。

```text:Width
If(App.Width < 800, App.Width * 0.9, App.Width * 0.7)
```
スマホなどの横幅が狭い端末ではできるだけ横幅を大きく使い、PCなどのデカイ端末では逆に余白を増やすことで視認性を高める、というようなレイアウトが可能ですね。

一応イメージ図も。
![SizingControls.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243135/4210388e-7526-f17f-2ebd-d01de8b4a7bf.png)


同じように、フォントサイズの指定などもしておくと良いと思います。

```text:Size
If(App.Width < 800, 25, 35)
```
みたいな。上記のサイズは適当ですが、画面が小さければ小さめのフォントサイズで、大きければ大きめで、みたいな指定ですね。


# もう少し高度なレイアウト
基本的には上記の内容である程度出来る気がしますが、もう少し凝ったレイアウトを考えてみたいと思います。
とはいえ単純なものですが…汗

### 縦に二分割してそれぞれセンタリングしたい
先程のセンタリングでやったことをもっと細かくする感じです。
文字での説明が大変なので図で済ませます。（ごめんなさい）
![SplitHorizontally.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243135/19f24d7a-da45-a02e-8a53-873f67c552f1.png)

### 横に2分割してそれぞれセンタリングしたい
縦の場合と同じ感じでいけますね。Yに対して計算するだけです。
![SplitVertically.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243135/14f5e917-963e-c46a-c213-6823e6afe57c.png)

こんなかんじですかね。
というか、今書いてて思いつきましたが、透明なコントロールを半分の幅で2つ並べて、そのコントロールに対してセンタリングすればこんな面倒な計算いらないんじゃ…(-_-;)

まぁ、私のような意味のないリソースは省きたい！という人はこっちでも良いかもしれませんね！ 

---
レスポンシブに関しての説明は以上です！
慣れてしまえば簡単ですが、最初に理解するまでがちょっと複雑だなと思ったのでまとめてみました。

早いとこ標準の機能でセンタリングや相対レイアウトが出来るようになって欲しいものですね…