[power apps]テニスコート申請画面を作成する Part11 レスポンシブ表示の実装(レスポンシブ対応/全手順公開)

やること

  • スマートフォン、タブレット、パソコンでそれぞれ適切なサイズでオブジェクトが表示されるようにする。

手順

1.自動リサイズ機能の無効化

Power Appsでは画面のアスペクト比を維持しながら画面をリサイズする機能がある。
この機能が有効になったままだとレスポンシブ対応ができないため無効に設定する。

  1. Power Apps左下にある設定の歯車マークをクリック
  2. 表示をクリック
  3. 画面に合わせて倍率を変更をオフにする

2.ブレイクポイントの設定

App オブジェクトのブレイクポイントを以下のように設定する。

SizeBreakPoints: [600, 900, 9999]

ブレイクポイントはスマートフォン(~600px)、タブレット(601 ~ 900px)、PC(901 ~ 1200px)、大きめのPC(1021px ~)で4段階設定することができる。
実際のところ、今回のアプリで一度に表示される項目数はそこまで多くないため、細かくブレイクポイントを設定する必要はない。

そのため、スマートフォン、タブレットをパターン1、PCをパターン2としてレスポンシブのレイアウトを組んでいく。
ブレイクポイントの3番目の幅を「9999」にしているため大きめのPCのパターンは考えなくてよい。

3.グリッド幅の更新(失敗案)

本アプリではグリッドレイアウトでオブジェクトを配置していく。
画面を12のグリッドに分割して以下のように、オブジェクトの幅を決めていく。

Width: LayoutDesign.GetCardWidth(6, 4, 2)

上記の例ではスマートフォンでは、12グリッドのうち6グリッド使用するので、画面幅の半分表示するというもの。
しかし、実際のところこのような書き方ができない。コンポーネントの自作関数を通してWidthを設定しても、なぜか画面描画に反映されないバグがある。
ゆえに自作関数を使わずにWidthを定義する必要がある。

4.グリッド幅の更新

代替案としてタイマーイベントを用いて画面幅の配列を用意する。

  1. 「+新規」 > 入力 > タイマーを挿入 (RefleshWidthTableTimer)
  2. 以下の通りプロパティを設定
    /** 1秒おきに配列が更新されるように設定 */
    Repeat: true
    Duration: 1000
    AutoStart: true

    続いて、OnTimerEndイベント関数で2つのテーブルFormCardWidthTableFormCardInnerWidthTableを更新する。
    これにより、ユーザーが画面サイズを変更しても、常に画面の1/12や6/12の幅を取得することができる。

    Set (
        FormCardWidthTable
        ,
        Table(
            {val: App.ActiveScreen.Width * 1 / 12}
            , {val: App.ActiveScreen.Width * 2 / 12}
            , {val: App.ActiveScreen.Width * 3 / 12}
            , {val: App.ActiveScreen.Width * 4 / 12}
            , {val: App.ActiveScreen.Width * 5 / 12}
            , {val: App.ActiveScreen.Width * 6 / 12}
            , {val: App.ActiveScreen.Width * 7 / 12}
            , {val: App.ActiveScreen.Width * 8 / 12}
            , {val: App.ActiveScreen.Width * 9 / 12}
            , {val: App.ActiveScreen.Width * 10/ 12}
            , {val: App.ActiveScreen.Width * 11/ 12}
            , {val: App.ActiveScreen.Width * 12/ 12}
        )
    );
    
    Set (
        FormCardInnerWidthTable
        ,
        Table(
            {val: App.ActiveScreen.Width * 1 / 12 - 60}
            , {val: App.ActiveScreen.Width * 2 / 12 - 60}
            , {val: App.ActiveScreen.Width * 3 / 12 - 60}
            , {val: App.ActiveScreen.Width * 4 / 12 - 60}
            , {val: App.ActiveScreen.Width * 5 / 12 - 60}
            , {val: App.ActiveScreen.Width * 6 / 12 - 60}
            , {val: App.ActiveScreen.Width * 7 / 12 - 60}
            , {val: App.ActiveScreen.Width * 8 / 12 - 60}
            , {val: App.ActiveScreen.Width * 9 / 12 - 60}
            , {val: App.ActiveScreen.Width * 10/ 12 - 60}
            , {val: App.ActiveScreen.Width * 11/ 12 - 60}
            , {val: App.ActiveScreen.Width * 12/ 12 - 60}
        )
    );
    

5.データカードの表示順序を変更

レスポンシブ対応を行う前に、各データカードの表示順序を並び替える必要がある。
各フォームにおけるデータカードの表示順序は以下の通り。

  • 会場選択Form: 検索条件会場ID > 会場ID > 会場名 > 会場都道府県 > 会場市区町村 >  会場住所
  • 日程選択Form: スケジュール候補日1 > スケジュール候補日2 > スケジュール候補日3
  • 備品選択Form: レンタルテニスウェア個数 > レンタルテニスボール個数 > レンタルラケット個数
  • 代表者入力Form: 代表者名_姓 > 代表者名_名 > 代表者かな_せい > 代表者かな_名 > 代表者電話番号タイプ > 代表者電話番号 > 代表者メールアドレス

データカードの移動方法はオブジェクトをクリックすると「カード」という黒い吹き出しが出るので、それをドラッグしたまま挿入したい場所のところでドロップ。

6.Widthの設定

データカードの各Widthプロパティに対して、以下のように設定する。
sm, md, lg, exはそれぞれスマートフォン、タブレット、パソコン、大きめのパソコンにおけるグリッド数を1 ~ 12で指定する。

With(
  {cols:[{col:sm}, {col:md}, {col:lg}, {col:ex}]}
  , Index(FormCardWidthTable, Index(cols, App.ActiveScreen.Size).col).val
)

 

例えば、以下の例であれば、スマートフォンとタブレットであれば画面全体(12 / 12)に表示し、パソコンであれば半分のサイズ(6 / 12)で表示する。
大きめのパソコンについてはブレイクポイントを9999に設定しているため、そのグリッド数が参照されることはないため、常に12を設定する。

また、「2.ブレイクポイントの設定」でも言及したように、項目数が少ないので、実際に指定するグリッド数は「4,6,8,12」くらいである。
そのため、スマートフォンとタブレットのグリッド数は同じ値を設定していく。

With(
  {cols:[{col:12}, {col:12}, {col:6}, {col:12}]}
  , Index(FormCardWidthTable, Index(cols, App.ActiveScreen.Size).col).val
)

つまるところ、指定する値は「A」「B」だけを考える。

With(
  {cols:[{col:A}, {col:A}, {col:B}, {col:12}]}
  , Index(FormCardWidthTable, Index(cols, App.ActiveScreen.Size).col).val
)

各FormのWidthの設定が完了したレイアウトが以下の通り。
青色の数字がデータカードに対するグリッド数でFormCardWidthTableからWidthを取得している。
オレンジ色の数字がデータカード内部に対するグリッド数でFormCardInnerWidthTableからWidthを取得している。

2つテーブルを用意した理由は「余白を作るため」である。
例えば、会場選択Formの「会場都道府県」についてオレンジ色のグリッド数だけを適用することを考える。

会場ID会場名のグリッド数は2 + 4 = 6であり、全体12から6引いて6余る。
余っていればグリッド数6未満のオブジェクトはその後ろに表示されるため、会場都道府県(2) と会場市区町村(2)が後ろに回り込んでしまう。
よって、会場ID会場名都道府県会場市区町村が1行にまとまって表示され、若干見づらくなってしまう。

一方で青色のグリッド数について考える。
会場ID会場名は2 + 10 = 12であるため、確かにその後ろに会場都道府県が割り込むスキマはない。
ただし、データカード内部のテキストボックスやラベルのWidthはデフォルトで「Parent.Width - 30」が設定されている。
そうなると、会場名のテキストはParent.Width * 10 / 12 - 60となり、長くなりすぎてしまう。

ということから「余白を設けるための青色のグリッド」と「内部のオブジェクトが長くなりすぎないためのオレンジ色のグリッド」が必要なわけであった。

■パソコン用レイアウト■

■スマートフォン/タブレット用レイアウト■

5.最小画面幅の設定

個々のオブジェクトに対するWidthは設定できた。
最後に画面全体のWidthに制限をかける。
プレビュー画面を表示させると、ブラウザの幅 = アプリの幅になっている。
ブラウザを最大化すると、各項目がデカデカと表示され、なんとなくかっこ悪い印象がある。

そこで以下のプロパティに変更を加える。
これで画面をどれだけ広げても、アプリ画面としての最大幅は1024pxで制限することができる。

Width: Min(Max(App.Width, App.MinScreenWidth), 1024)

記事一覧