【後半】ProtoPieでMVCに挑戦!(後編)
前編はこちら。
前編を読んで、それでもProtoPieで作ろうと考えている場合、おそらくある程度複雑なものを作ろとしていると思われます(笑)
MVCを意識しよう
そこで重要になってくるのが、MVCです。序盤で説明した通り、MVCというのは(大まかに言うと)ロジック部分と表示部分の実装を切り離そうという考え方なので、それを意識していないとProtoPieでは、プロトタイプの構造が非常に複雑になって変更や追加が難しくなります。(ほぼプログラムを書いて実装してる状態に近くなってきます)
まず、今回デモでつくるものの完成系をご確認ください。
下記のリンクからでも実際に触って確認できます。また、Macからアクセスすることで、プロジェクトファイルをダウンロードしてProtoPie Studio(ProtoPie制作用のソフトの正式名称)上でどうなっているのか確認することもできます。ご自由にダウンロードしてご利用ください。チュートリアルを詳しく読むより、実際に触ってみた方が分かることも多いので、そういったやり方もオススメです。
さて、今回のプロトタイプ。よくある3列のタブUIです。
ポイントになるのが下記の2点
1. 左右のスクロールでタブ遷移ができる
2. タブ自体をタップしても該当ページにジャンプすることもできる
どちらか片方だけを実装するなら、XDなどのオートアニメーション系でもできますが、両方動くようにするのは至難の業です。
大まかには下記のような考え方で作っていきます
ステップ1: 横スクロールする「ページ」を準備する
ステップ2: 「タブ」を準備する
ステップ3: デバッグ用の変数を用意する
ステップ4: 状態を管理する変数を用意する
ステップ5: ユーザーの操作に応じて、状態(ステップ4)をアサインする
ステップ6: 状態に応じてViewの見た目を変更する
めんどそうwww
もはやデザイナーのやることちゃうやろとかいう声が聞こえてきそうですが。(それは言ったらあかん!🥺)
ステップ1: 横スクロールする「ページ」を準備する
まずは下記のように3枚のページを横に並べます。操作した時にわかりやすいように色と数字を変えてあります。前半で説明した、「抽象化しよう」の部分ですね。シンプルですが、今回検証するインタラクションとしては必要十分で明快です。
レイヤー構造は下記の通り
3つのページをScroll Viewというコンテナーがまとめている。
注意して欲しいのは、Scroll Viewの範囲。デバイスの縁と一致させることで、はみ出た分のコンテンツが「スクロール可能」になる。
**Scroll Viewのスクロールの設定を行う **
Scroll Viewのコンテナーを選択して、インスペクタで上記のように設定。Pagingオプションを選択することで、自動的にページごとにスナップしてくれる「Paging Scroll」が可能になる。「方向」は今回の場合水平方向なので、↔︎でOK。
ステップ2: タブUIを準備する
Tab 1, 2, 3を作った状態。四角形ツール、テキストツールのみで構成されたシンプルなもの。デフォルトではTab 1を選択状態、それ以外を非選択状態の見た目にしている。濃いグレーは#343A40、薄いグレーはADB5BD。ProtoPieのプリセットカラーです。
レイヤー構造はこの通り。レイヤーの名前をある程度ちゃんと書き換えておくと後々便利。
ステップ3: デバッグ用の変数を用意する
今回、スクロールでページを切り替えた際に、今どのページにいるかという情報を制御する必要が出てきます。Scroll Viewの中身がどれぐらいスクロールされたかを知ることで、それが可能になります。そのために用いる変数を今回は「デバッグ用の変数」と呼んでいます。(ページ番号を判定するためにも使っているので、厳密に言うと単なるデバッグだけのための変数ではありませんが。)
変数の作り方
ProtoPieの変数作成は画面左下のエリアから行う。
早速変数作りましょう。
今回のプロトタイプは1画面(=シーン)で完結するので、「このシーンのみ使用」を選ぶ。基本的には、「このシーン」のみにして、画面が増えて複数画面での状態管理が必要になった場合に「全てのシーン」を使用するようにしておけばよい。
スクロール位置を知りたいので「scroll_offset」という変数名に。
「scroll_offset」をクリックすると、画面右のインスペクタエリアで、変数の初期設定が可能になる。
「スクロール位置」は数値なので「数字」を選択し、初期値は0でOK。Booleanのような型はないので、YES/NOを返すような場合は、「テキスト」型を使って"YES" or "NO"とするか、数字として「0 or 1」とするような方法がある。今気づいたが、カラーを変数として管理できるようにもなっている模様。
スクロールイベントをDetect(検出)する
スクロール距離を取得するために、まずスクロールイベントを検出します。
1. レイヤー「Scroll View」を選択
2. トリガーを追加
3. 「Detect」を選択。
1. 「Detect」を選択し
2. Scroll Viewレイヤーの
3. 「スクロール」アクションを検出するように設定する
1. Detectの下の「+」マークを押して
2. Assignアクションを追加(Assignは変数に値を設定するアクション)
変数scroll_offsetを選択
GUIで変数をアサインするために、fxボタンを押す
Scroll Viewの・・・
scrollOffsetという値を取得。
「Scroll View.scrollOffset」となるように、リストから選択していく
変数のメニューにある「虫ボタン」を押して、変数の値をプレビュー画面で確認できるようにする
この時点でプレビューを確認すると、スクロール位置を画面上で確認できるようになっている。この値をもとに「現在のページ番号」を判定していく。この時点で見てわかる通り、1,2,3ページ目にいるときそれぞれのスクロールの値が0, 375, 750であることがわかる。
ステップ4: 状態を管理する変数を用意する
続いて、もう一つの変数active_page_numberを作っていきます。この変数が「今何ページ目」というのを管理することになります。先ほどと同じように変数の初期設定を行いましょう。
1. +ボタンから新規変数追加
2. 変数名をactive_page_numberに変更
3. 初期値は1ページ目なので「1」とする
ステップ5: ユーザーの操作に応じて、変数をアサインする
ユーザーのスクロールで、ページが切り替わった際にactive_page_numberの値を変更させましょう。
scroll_offsetの値が変わったことを検出して、その値に応じてactive_page_numberを変更する。
1. トリガーを追加
2. Detect(検出)トリガーを選択
3. scroll_offsetの値の変化を検出
Conditionを追加すれば条件に応じてアクションを分岐させることができる。
今回は、scroll_offsetの値が0の時はページ1、375の時はページ2、750の時はページ3となるようにactive_page_numberを設定する
scroll_offsetが0のとき・・・
active_page_numberは1になる
これをさらに2つ追加して、同様に設定する(トリガーやアクションはコピーペースト可能)
これで、ユーザーのページスクロールに追従して、現在のページ番号をトラッキングできるようになった。気になる場合は、先ほどと同様に虫ボタンを押して確認してみると良い。
次以降のステップでは、この番号に応じてTabの見た目を切り替えることになる。
ステップ6: 状態に応じてViewの見た目を変更する
次は、先ほど設定したactive_page_numberの変数を監視(例によってDetectイベントを使用する)しながら、値に応じて、Tabの見た目を制御していきます。
まずはDetectイベントを追加し、active_page_numberを監視しよう。
active_page_numberが1だったら・・・
Active Tab Indicator(テキストの下の黒いバー)が濃いグレー(#343A40)に変わる。
テキストのColorも同じく濃いグレーになるように設定。
active_page_numberが1じゃなかったら・・・
テキストと下のバーが薄いグレーになる
ここまでがTab1の制御。これらをコピーペースとして、Tab 2, Tab3も同様に設定します。
ここまで設定できれば、ユーザーのスクロールに応じて、選択中のタブの見た目が変更される。
プレビューモードで確認してみよう。スクロール操作に応じてアクティブなタブが変わっていることがわかる。
ここまで終わってみて、序盤で説明した通り、「ロジックと見た目の実装が分離」されていることがお分かりいただけるでしょうか?
ステップ5までで実装した部分(変数の設定部分)はアクティブなページの番号を管理しているだけで、見た目の変更は行っていません(=Controller的な役割)。ステップ5以降で実装している部分(オブジェクトのColorを変更する部分)は見た目の変更を担当していますが、アクティブなページが今どこかという管理は行っておりません。(=Viewを担当)
現時点でも十分動いているように思えますが、もう一つの機能を忘れてはいけません。それは、「タブを選択して直接該当のページにジャンプする」動作です。
やっていきましょう。
1. Tab 1レイヤーを選択
2. トリガーを追加
3. Tapトリガーを選択
Tab1にタップトリガーを追加しました。これによって、Tab 1がタップ可能なUI要素になりした。
1. アクションとしてAssignを選択し
2. active_page_numberの変数に
3. 1を設定
Tab 1がクリックされたということは、ページ番号を1にセットする必要があります。これを同様にTab 2、Tab 3にも設定します。
それぞれのアクションやトリガーは、任意の名称を設定できる。今回のようにある程度複雑の実装が必要な場合は、名称を設定しておくことで管理がしやすくなる。トリガーをグルーピングすることもできる(⌘+G)
最後に、先ほど作ったactive_page_numberに応じてTabの見た目を変更する箇所に、ジャンプスクロールの動作も入れていきましょう。
最初のCondition(active_page_number == 1)の部分に、Scrollアクションを追加。Scrollアクションは、スクロール可能なコンテンツを任意の場所までスクロールさせることができる。
1. Scroll Viewを
2.「指定値までスクロール」
3. 0
と設定。
同様の設定を、Condition 2と3に対しても行っていく。
Condition 2では、スクロール位置は375へ、
Condition 3ではスクロール位置を750に設定する。
最終的なView部分のアクションはこのようになる。
完成
完成したプロトタイプは下記より確認 and プロジェクトファイルごとダウンロード可能なので、実際にProtoPie上でどうなっているのか確認したい方はご自由にダウンロードしてご利用ください。
以上でした。
UI/UXデザインに関する情報発信をしています。この分野のコミュニティに貢献できるように、全てのnoteは無料で公開しています。サポートしていただけましたら、デザインのツールを購入するのに使いたいと思います。ツールの使い方や、レビューを投稿しておりますのでぜひご覧ください。