4/18/2014

[&] How to make Conference Apps



あんざいゆき×秋葉ちひろはカンファレンスアプリをどう作るのか?
---------------------------------------------------------------------
ABC 2014 Spring カンファレンスアプリ
https://play.google.com/store/apps/details?id=com.uphyca.abc2014s

(お二人ハモって)よろしくお願いします〜
どうデザインして実装したのかという話しです。

あんざいさん:Y.A.Mの雑記帳というブログがよく知られています。

秋葉さん:ツクロア、2人のデザイン会社です。今はハードウェアとかも....

今日の前半は設計、デザインについて、

●新しいアプリを作るステップ
1. 既存アプリの調査
2. ざっくり機能を考える
3. 構成(画面遷移)を考える
4. 各画面のレイアウトを考える
5. 実装する
6. 使ってみる

秋:動きだけ一緒に決めて、レイアウトを引き取る感じ、
あ:実装しながらも、デザインも変わっていって、
最初に決めてではなく、作りながら画面どうするかを
決めていったことも何個かありました。

●1 既存アプリの調査

- どういう機能があるか
- どういう構成(画面遷移)になっているか
- こういう機能もあればいいのになあ
「必要な機能がみえてくる」

秋:それぞれの個々のよいところの寄せ集めみたいなことはやります。
あ:すでにあるアプリを見ると、いいところはあるし、
そこから新しい発想も出てくるし、漠然と一から考えるのは難しい。
だいたい必要な機能が見えてくる。
機能作るまえに調査することが多いです。

秋:調べたアプリで使いにくいところを改善してやろいうということにもなります。

ABC 2014 Spring 関連のアプリ
ABC2013 Autumn 関連のアプリ
Google I/O アプリ
Google Play で「Conference」で検索した結果からよさげなもの

あ:あんまりいいのなかったよね〜
秋:WebView ですか〜みたいなのとか。
あ:ガイドラインにそった良いアプリが無かった
でも参考にならないわけではなかった、
良いアプリが無いと、よいアプリを作ってやろう!というモチベーションになった。
だいたい20個ぐらい見て、そこから機能を考えようと、

●ざっくり機能を考える

すでに既存のアプリであるもの、必要な機能は既存のアプリを見ているとわかる。
公式サイトに飛べるようになっていたり、
特定のタスク、ゴールを満たすようなものに特化していって
細かい情報はなんでもかんでも載せるべきではない。
ので、残りは公式サイトに行ってね〜

秋:載せすぎてもわからなくなるから〜
あ:講演内容を見るのが重要、それ意外にスケジュール作りたいとか、
お気に入りとしてチェックしたい、地図を見たいとか、
既存アプリには地図出てくるのが無くって.....

どんなに沢山セッションがあっても一つの時間には一つの講演しか見れない。
同じ時間帯の講演から、どれ見ようかなって考えるよね
→タイムテーブルが欲しい

秋:ユーザーになってみないと分からないですよね。
エンジニアは XML のデータがあるから、それを出すだけで終わってしまいますが、
ユーザーから見ると、時間軸が全然なかったので、
それはやっぱり重要だよねと気づくというプロセスは大事。

あ:いかに使う場面を想像できるのかというのが
使いやすいアプリを作れるのかになってくるのかな。
時間割みたいな、表みたいなのが、Webに載っているのですが、
それをそのままスマホに持っていくのは難しい。

タイムテーブルの項目をタップしたら応援の詳細がみたい
どれがお気に入りになっているか知りたい
どの部屋の講演か知りたい

タイトル、講演者、概要、時間、部屋、カテゴリが知りたい
カテゴリをタップしたらそのカテゴリの講演一覧が見たい
講演部屋の地図がみたい
お気に入りにチェックしたい

●しなりおを考える2(想像する)
バザールの見せ方って難しい
「地図が無いとつらい、常に見たい」
ブースの数が多いので、地図のどこにあるかすぐ見つけられるようになってて欲しい

色分けわかりやすい。
あ、い、う、え、か も別の色がいい

あ:色分けって分類したりする時に分かりやすいものだな〜と思ったんだよね。
色によって島がわかれているのであれば、色を見ればその島なんだなというのが
すぐわかって。
秋:色が脳にアピールする力は強い、記憶と結びつくと思って

その島のブースかすぐわかりたい
色分けの色を表示するとか
ブースがたくさんあるから下までいくのたいへん
インデクスラベル + fast scroll
ヘッダーが残るリスト

あ:パターンクックブックに載っているのがいい!と。
Android にもあるんだ〜と。

●詳細の要求

地図と一緒にみたい
地図を見るときにブース番号を覚えておかないといけないのはイヤ
どの島のブースがすぐわかりたい
色分けの色を背景にするとか
隣りのブースの詳細に簡単に移動したい
(ある島を流れ歩きでぐるっと見て回るときとか)

あ:今回ABCにいって、インプレスのブースに行くまでに苦労し.....
地図重要です。
秋:デザイン作らずとも色付きのものを作ってくれていてわかりやすい!と思って
あ:スワイプすると、隣りのブース情報に行けるんですよ。
便利だな〜と思ってそうしています。

●お気に入りの要求
それをみて行動するからスケジュールっぽくなっているのがいい
時間順に講演が並ぶ
地図が常にでている

あ:今回考えていて、講演内容が見えるのが重要ですが、その次ぐらいに
地図が重要かなと。
秋:今回会場が離れていたんだよね。紙の地図みても.....

あ:最後に実際使っていて、開場までの Google Map も無いと、
日付とか住所とか出ていて、そこから Google Map が開けるようになっています。
秋:すごくいい!

●トップレベルの画面
タイムテーブル
お気に入り(毎スケジュール)
カンファレンス一覧(カテゴリごと)
画面きりかえを使いたい
Navigation Drawer

あ:タブだとちょっとダメなので、Navigation Drawer かな〜と

●タイムテーブル
タイムテーブルを載せたいと、それを一画面に入れるのは
相当無理。

特定の時間枠ごとにどれを見るか考えるなら、時間枠ごとに1画面にするのはどうか
→横軸を時間にする
→スワイプで隣りの時間枠に移動

あ:横軸を時間にしたのはナイス!という人も入れば、
ぱっと見わからないという人もいて....
秋:慣れるとわかるけど。
あ:画面のデザインというよりも情報デザイン的にどういう画面があるとか。
隣りの時間軸に行けるとか、全体のでっかいタイムテーブルの一部分を
見るようにしたかった。

講演詳細の画面遷移
特定の講演の情報
地図アイコンタップ→地図
カテゴリタップ→そのカテゴリの講演一覧

秋:地図をボタンで設置したのは、内容を見るのは、前日ぐらいで、
この画面の中に常にだしておく必要は無いかなと。

●カンファレンス一覧の画面遷移

あ:個人的にはタイムテーブルがあったら、タイムテーブルしか見ないんじゃないかなと。
特定のカテゴリを見たい人はいたいのかな?
とりあえず、デザイントラック、残りの時間は他を探すとか、
秋:サブ的でもいいので、ある方がいい。

●バザールの画面遷移

秋:あるきながら使うという想定もあり。

●お気に入りの画面遷移

あ:お気に入りが最初と最後で一番変わったところ。
バザールもお気に入りつけたかったんで、
最初一画面に入れようと思ったのですが、
一画面だと、微妙だったんだよね。スワイプで隣りになるようにしました。

●各画面のレイアウトを考える

メインの色を決める
タイムテーブル
詳細
お気に入り
バザール
マイスケジュール

秋:考える時は考えるのですが、ネイティブUIを使うときは、
使う要素が決まっているので、色をどうするのか?ぐらい。

メインの色は白ベース、色は最初に2人で話していて、
黒ベースは無いよな〜 白ベースでアクションバーをグレーにする?
グレーは暗くなってしまう時があって、
白がメインカラーで、サブカラーでグレーを使っていて、
それだけだと葬式っぽくなるので、
ABC なので、ドロイド君の黄緑と、オレンジをここで使ったのですが、
黄緑の補色で。青だと死んでしまうので、オレンジを目立たせる色として
選びました。

あ:補色選ぶのって難しい? 近くに置くとパキパキしてしまう。
秋:そこは感覚でやっています。

●タイムテーブル
ActionBar のタブではなく、ViewPager TabStrip
文字のジャンプ率と色で情報の優劣をつける

秋:大きくする必要は無いなと思ってViewPager TabStrip
タイトルが黒なんですよね。人の名前がグレーなんです。
両方黒だと見分けが着かなくなる。
ジャンプ率、大きさの比率を考えて、どちらかを小さくすると
見やすくなると思います。

●詳細が面
ヘッダで領域をとらないように
文字がかぶらないように

あ:配置を悩む画面だよね
秋:要素は少ないけど、項目がおおくって、



タイトルが長いと、追加ボタンが被ってしまう。
右に変えて、線を入れてましたが、線無い方がいいんじゃない?
横幅を延ばして、余白を狭めるかたちで、中のコンテンツが上の方に来るように工夫しました。

秋:綺麗になったよね。
あ:そうだね。カテゴリの色があってていいよね。

●お気に入り
アイコンだけだとわかりづらい
マイスケジュールに登録



秋:しおりのマークだけだとわからないじゃないですか。
背景色もつけたのですが、上下2列並んだときに、
今は余白付きのオレンジにしました。

あ:へ〜 なるほどなるほど

「マイスケジュールに登録」文言を吟味
「登録」だけだとわからないし、どっちが自然かな?と思って、
「マイスケジュールに追加」

あ:出て来たものをホイホイ作ってたのに。

秋:お気に入りのオレンジがなかったらこんなに悩まなかったのに、
真ん中も綺麗だな〜と思ったんですが、
あ:場所が小さくてぱっと見わかりにくい。



●マイスケジュール

あ:最初、これはないだろ〜
すでにお気に入りにしたものしかここには入っていないハズなので、
秋:まだ未登録の場合、これどうしようとなって。
今、エンプティの画面作るときこつがあると思っていて、
上に寄せてしまうと、カッコ悪い。何も無い画面を楽しく見せないといけないと
考えていて、エンプティの枠の中で、上下方向の真ん中ぐらい。
真ん中に何かを配置すると、エンプティ画面っぽい感じがして、
ドロイド君が真ん中にいて、
探すというボタンがあって、無いと、どっから何をするのかが
分かりにくいから。

あ:画面上に追加ボタンがあって、→を向けて、みたいなのがあって、
Navigation Drawer を出すところを示そうかな〜と思ったけど、
今回は直接飛べた方がいいかな〜と思って、
バックボタンを押すと、アプリが終了しちゃって、そこの遷移に
悩んでいて、エンプティの画面からアクションに飛んだ時に、
どうやって階層構造を持たすのかが難しい。

秋:階層構造難しいですよね。
あ:いっかいチラ見せしてからかな〜と思って
作りながら悩んでいることが多いです。

後半は実装の話しをしたいと思います。

Q. 画面のレイアウトを考えたり、デザインを考えたりするとき、紙?ツールを使ったり?
A.
あ:最初相談したときは、ノートに書きました。紙に書くと、その後わりに綺麗なものを作るときは?
秋:紙で書いたやつを、144pix とか、かっちり決めてイラストレーターで起こしています。

Q. 機能を考えた後に、遷移図はどの段階で作りますか?
A.
あ:一人で作ったからだと思いますが、ちゃんとした画面遷移図は作っていません。
ノートに書いた時に、設計段階で画面の関係性は決めてしまう感じ。

Q. デザインをイラストレーターで作っているという話しでしたが、Photoshop ではない理由は?
A.
あ:テクスチャモリモリのころは、Photoshop でしたが、フラットデザインになってから、
イラストレーターでちょっとグラデーションつくれるくらいで、早く作れる。
クリエイティブクラウド版を使っています。

Q. ノートは実際にどのくらい細かく書いてますか?
A.
あ:わたしかなりがっーっと書いて、かなり汚いですが、
秋:A4 のノートに小さい感じで書いていくぐらい。
あ:ステンシルとか、枠が印刷してあるのとか、使ってないです。
けっこう殴り書きな感じです。

---------------------------------------------------------------------------------------
後半:実装編

あ:ABCのサイトで公開されている XML をまずパースします。
ローカルDBに入れて、見るという形になっています。

今回難しかったのは、一個のカンファレンスの中に
スピーカーの ID を持たせて、
スピーカーが複数なので、いい方法があったら、それやりたいんですが、
スピーカーの IDをセミコロンで結合して、
分解して、スピーカーテーブルからひっぱってきて表示するという形にしました。

カンファレンスアプリを一般カンファレンス用に拡張するとか、
このへんを上手く考えて、最終的には XMLからそのままDB設計を考えるのではなく、
こういうDB設計になっていればアプリとして使いやすいという風に。

秋:XMLは使われていない?

最近は JSONの方がうれしい。
XMLだと文字列処理をしなければいけないが、
JSONだといろいろやってくれるライブラリがあるので楽。

バザールも、IDと出展者の名前が group になっていたり、
ここもちょっと悩んでいたのは、ロケーションの情報が「イ1」とか
それだけなんですよ。
そのへんがアプリとして使いやすい API設計に関係していくと思うのですが、
今回は「ア」はどの島なのか、しょうがないので、むりくり。
そのへんの島と番号は別にして、APIを設計して欲しいな〜というのがありました。

秋:API設計の問題もあるんですね。

あ:コードを書き換えないといけないので、優しい設計ではない。
今回フラグメントを使っているのでActivity はあまりない。
MainActivity にほとんど入っている。
スワイプのところもフラグメント、
マイページもフラグメント
バザールもフラグメント
かなり沢山入っています。

Navigation Drawer は一個の Activity に沢山フラグメントが入る事になります。
カンファレンス一覧のアクティビティもそれだけ。
最初はタブレットのことも考えたのですが、
間に合わなかったのですが、タブレット対応も一応考えてあります。
詳細をタップしたらというタブレットの構成にしたい場合も考えて。

バザールの部分も、スワイプで下の部分が変えられるようになっていて、
ViewPager の中がフラグメントになっています。
画面遷移は今日初めて作りました(笑



秋:詳細にはいろんなところから行けるんですよね。

タイムテーブル
ViewPager
PagerTabStrip
ListFragment
複数の Cursor を持つ
Adapter

フラグメントの中にフラグメントが入っているような構成になっている。
APIレベル17以上になっているのはそういう理由。
LTって同じ枠の中に複数のセッションが入っているので、
カラムを一個にしたいということで、
各部屋が Cursor で、複数の Cursor を持つアダプタという実装になっています。

複数の cursor を持つ Adapter
連絡帳アプリで使っているのがあって、
ヘッダーの表示も対応している。
http://tools.oesf.biz/android-4.4.2_r1.0/xref/frameworks/ex/common/java/com/android/common/widget/CompositeCursorAdapter.java

BaseAdapter を継承していて、
パーティションを内部で持っていて、この中に cursor も持っていて、
中に cursor 、うまくポジションを渡してくれたり。コードを読んでみるといいです。
それを使うと、
それぞれのパーテションに対して、そこの cursor を取ってこれて、
cursor に一個しか入ってなければ、時間を表示していなくて、
複数の cursor が入っている時はLTの時間を表示する実装になっています。

●カテゴリー一覧
ListFragment
SimpleCursor Adapter
カテゴリー名(カテゴリーIDのCursorを作る)
重複していないヤツが欲しい。
ただ単にコンテントプロバイダーからカテゴリを取ってくると、
IDが違うから、同じカテゴリ名が並んでしまう。
SQLの group By を使う。
カテゴリでグループにして、そのリストを作る。

Content Provider で group By を使うのはベタの方法しかなく、
appendQueryParameter で取得して、そのまま group by に渡す。
結構SQLを理解していると、Java側で頑張らなくても、欲しい cursor を取ってくる
方法があるので、知っていると楽。
罠があって、
SimpleCursorAdapter には _id カラムが必要
group By したカテゴリーIDを as を使って _id として取得

カーソルラッパーを使う方法もありますが、SQL を使うと良い。

すべてのトラックを表示するための行もほしい
MargeCursor を使って Cursor を合体
すべてのトラック用の Cursor は MatrixCursor で用意

秋:すごいですね!簡単そうに見えて.....

ほんとに楽しようとおもったら、カテゴリの表示を文字列にしておいて、
のちのちこれを次のカンファレンスで使おうとおもったら、
ハードコーディングはできないので、
こんなことをしないと。

秋:すごい考えているんですね!

次回使うことも考えて、書いているのですよ!

スピーカー
ListFragment
SimpleCursor Adapter
カンファレンスのテーブルにはスピーカーID
スピーカー名は別テーブル

スピーカーのIDを名前に変換しないといけない。
カンファレンスのテーブルにはスピーカーの IDが ; 区切りで入っている。
シンプルカーソルアダプターでごにょごにょやりたくない。
スピーカー名に変換されているカラムがあって、それを表示するだけ
にしたくて、どこでごにょごにょ変換するかというと、
CursorWrapper を使いました。

CursorWrapper と何がいいかというと、内部で実際にテーブルから帰ってきた内容に
編集したものを返したいとか、ごにょごにょした部分を隠せるのが利点です。

カンファレンスの詳細
ListFragment
ヘッダー
カンファレンス情報
リスト本体
スピーカー
お気に入りボタン

結構がんばったのは HTMLボタン。
HTMLボタンをCSSで動きを書いたのが送られてきて.... 中身読みました。

FrameLayout を継承した CustomView
ToggleButton と★を重ねたレイアウト
CHeckable を実装し、ToggleButotn に流す
ONでアニメーション
トグルボタンですが、チェックボタンの属性を指定しています。

秋:そうなっているとは知らなかった

見た目はそんなに難しくないです。
一番難しかったのはバザール一覧

ListFragment
各島が一つの Cursor
複数の Cursor を持つ Adapter
FastScroll +ヘッダーが残る

CompositeCursorAdapter を改造
もともとヘッダーの表示に対応している
ヘッダー情報を使ってインデックスラベルを作成
ヘッダーの残るリストに対応

CompositeCursorAdapter に辿りつくまで試行錯誤した感じです。

マイスケジュール
ViewPager
PagerTabStrip
Fragment + ListView

実装はだいたいこんな感じなんですが?どうなんですか?

秋:デザインしてもらってから実装するまで時間がかからなかったのですが、
こんなにめんどくさいことをしているのかと思うと、心が痛みます。

あ:デザインからすると、どれが簡単で大変なのかが分からないですよね?

秋:ここまでの動き、触ってて気持ちいい。これ作ってもらって「いいな」となりました。
あ:うふふ

秋:逆にデザインに対して「くっそー」っていうのは無いですか?
あ:最初、どうやって内側に入れればいいんだべなーと思って

秋:今思うと Web っぽいかなと。
あ:内側の区切り線も、あのへんとかも、最初どうしようかなと悩んでたんですよ。
秋:そこはデザイン都合しか考えられないですよね。
あ:けっこうチャレンジングなデザインでした。でも出来るってことで。
「あんざいさんが出来る!って言ってました!」と言ってください。

Q. ABC の API はリアルタイムで更新されるようになっていますが、更新を
リアルタイムで取るとして、どのタイミングでトリガーにするか?更新ボタンはどこに入れるか?
A.
あ:リアルタイムでやると Sync サービスみたいのがあって、
Google I/Oもコンテントプロバイダーで同期する。
ひっぱって更新する? タイムテーブルに入れると変
秋:何が更新されるかわからない。
あ:プッシュでやるべき? プッシュは API 出している人でないので分からないですよね?
秋:そもそも更新があるものではない。
あ:でも前日とかにいっぱい変更が来るんだよね。
秋:オーバーフローに入れる。こっそり。

Q. アクティビティにするか、フラグメントにするか悩むのですが。トラックの一覧から、
講演一覧、講演詳細はアクティビティですが、
フラグメントの判断基準は?
A.
あ:階層構造をフラグメントでやるのは好きでなくて、
同じ階層の切り替えはフラグメントでやって、階層が変わるところはアクティビティで。

Q. デザイン側とプログラミング側で、アクティビテイ/フラグメントは細かい話しをするのですか?
A.
秋:アクションバーとかデフォルトUIを使おうという話しだけ。