プログラマってこんなかんじ??

アプリ作ったり歌ったりしてます

Android Design のパターンを実装してみた(Patterns - Multi-pane Layouts)

Android Advent Calendar 2012 12/18(裏) 担当の @daichan4649 です。
よろしくお願いします。


経緯

Android Design のサイト、ありますよね。Android公式から提示されてるガイドライン。アプリはこう作ってねとか、画面遷移はこういう風に、とか、アイコンはこういうサイズで、とか。しかし、コード例へのリンクがない。理想のパターンを定義するなら一緒にコードも公開してくれたらいいのに。

なんて思いから 「自分ならこう実装する」 というのをやってみました。実際にはどう実装するのがベストプラクティスなのかわからないので、コード晒すのでみなさまぼこぼこにしてください。 #ドM


Multi-pane Layouts

Android Design にはいろんなパターンが書いてありますが、まずは Patterns の中から Multi-pane Layouts をチョイスしてみました。

Combining Multiple Views Into One
1. 同一apk で 小さい端末では 1pane 、画面大きめな端末では 2pane にする
2. 親(リスト) を選択すると 子(詳細) を表示する

よくある 2pane なアプリのパターンについて、ですね。とりあえず、このパターンのサンプルアプリ作ってみました。サイトではタブ表示になってるけども、今回そこは関係ないのであえて無視してます。


スクリーンショットです。


小さめの端末(Galaxy Nexus)

初期表示
f:id:dai4649:20121217235708p:plain

リスト選択
f:id:dai4649:20121217235722p:plain


大きめの端末(Nexus7)

初期表示
f:id:dai4649:20121217235746p:plain

リスト選択
f:id:dai4649:20121217235937p:plain


それではアプリの実装について説明してみます。


1. クラス構成

  • Activity 1つ
  • Fragment(リスト)
  • Fragment(詳細)

ここはシンプルに。


2. レイアウト

本当はもっと細かくサイズ指定すべきなんだろうけど、めんどくさいのでこんなかんじで2つ用意。

  • 画面小さめな端末向け(/layout)
  • 画面大きめな端末向け(/layout-large)



3. Fragment の表示/入れ替えロジック

画面小さめな端末(1pane)
  • 初期表示
    • コンテナ(android.R.id.container) を Fragment(リスト) で replace
  • リスト選択時
    • コンテナ(android.R.id.container) を Fragment(詳細) で replace
画面大きめな端末(2pane)
  • 初期表示
    • 左側に Fragment(リスト) を表示
    • 右側に コンテナ を表示(空)
  • リスト選択時
    • 右側のコンテナ を Fragment(詳細) で replace

xml ごとに構成を変えます。



で、この手の Activity1つ、Fragment複数、なパターンを使ったときにいつも悩むのが データの管理。コンフィグ変更(縦横切替等) で Activity が再生成された際の挙動を考慮して、こんな感じで考えてみました。


4. データ管理

CRUD

Fragment から Activity を参照(Fragment#getActivity)し、「必ず」 Activity 経由でデータをいじる。

保持

Activity 内でデータ保持


今回は 「コンフィグ変更(Activity#onDestroy)時にデータ破棄」 するような作りにしているため、Activity で単純にデータ保持しています。「コンフィグ変更時にデータ破棄」 させたくない場合は Fragment#setRetainInstance(true) な Fragment で管理すべき、だと考えてます。このあたりについては前に以下のエントリでまとめてみました。


Activity再生成時のデータの保存・復元(Fragment#setRetainInstance)



これを基にすると、各 Fragment でデータを表示するまでの流れはこのようになります。


5. Fragment でデータ表示するまでの流れ

  • Fragment(リスト)
    • Fragment のインスタンスは Activity 表示時 にレイアウトから生成
    • onActivityCreated で Activityからデータ取得
    • adapter に取得したデータを設定
  • Fragment(詳細)
    • Fragment のインスタンスは リスト選択時 にコードから生成(引数: 選択位置)
    • 生成時に引数で渡された 選択位置 を内部保持(Fragment#setArguments)
    • onCreateView で ↑の 選択位置 を基にして Activity から 表示用データ を取得(Fragment#getArguments)



アプリの構造、設計はざっくりこんなかんじです。コード本体は ここ(github) に置いてます。今回記載した以外のパターンについても実装したら(需要はおいといて)公開していこうと思っています。


最後に

去年 に引き続き、今年もこのようなすばらしい企画に参加させていただき、主催の @youten_redoさん、参加者の皆さま、本当にありがとうございます。来年も参加できたらいいな!明日 12/19 の担当は @androidsolaさん(表)、@furusin_oriverさん(裏) です!


追記

事件です。最新のADT (21.0.1 現在)では、マルチペインな雛形を自動生成できることが発覚しました!!m9(^Д^)
あれ、目から水が。