カード型ユーザーインターフェースを適応する


Androidではフラットなデザインのアプリケーションが増加しています。その中でもSNSなどで増えてきているカード型UIの作り方についてここではご説明します。カード型UIは必要な情報がまとまっているということを主眼においたフラットなユーザーインターフェースのことです。
このカード型UIはWindowsPhone7/8やiOSではすでに採用されており、GoogleのアプリケーションであるGoogle+、Google Nowはカード型UIになっています。

カード型UIの基本的な動作は次のようになります。

カード型UIの動き

カードの一覧が表示され、下へスクロールすると次々追加されていき、アイテムを選択すると選んだアイテムの詳細画面に遷移します。
このような別の画面へ切り替わり、戻るボタンにて前の画面へ戻るアプリケーションを作るにはフラグメントのバックスタック機能を用います。

ここではバックスタックの使い方とカード型UIの作り方についてご説明します。
ただし、カード型UIの作成にはListView、Animationの知識が必要となります。

カード型UIを実現にするには下記の手順が必要です。

  1. ListViewのカスタマイズ
  2. ListViewのアイテムを選択した時に別の画面へ遷移

これらについて説明していきます。

フラグメントのバックスタック機能の使い方

AndroidのFragmentを管理するFragmentManagerにはアプリケーションのバックスタック機能が用意されています。
このバックスタックというのは表示中のFragmentの状態をFragmentManagerに保存し、別のFragmentに切り替え、戻るボタンを押した時に現在のFragmentを消し、前のFragementを表示することができます。

FragmentManagerにバックスタックを保存した場合にはメモリが枯渇するまではFragmentをバックスタックに貯めることができます。
ただし、メモリが枯渇するとFragmentは破棄されてしまうため、メンバ変数に持っているデータは消えてしまいまうため注意が必要です。

それでは使ってみましょう。
Fragmentを別の画面へ切り替える場合には次のような手順を踏みます。

  1. FragmentManagerを取得
  2. FragmentTransactionの取得
  3. フラグメントの置き換え指定
  4. フラグメントの置き換え

この3と4の間で現在のFragmentを保存するaddToBackStackを行うことでFragmentを保存することができます。
addToBackStackの引数はString型でスタック名を与えることができますが、nullでも問題ありません。

        FragmentManager fragmentManager = getFragmentManager();
        FragmentTransaction fragmentTransaction
                = fragmentManager.beginTransaction();

        fragmentTransaction.replace(R.id.layout_fragment_area, fragment);
        fragmentTransaction.addToBackStack(null);
        fragmentTransaction.commit();

これでバックスタックにFragmentを追加することができました。戻るボタンを押すと自動的に前のFragmentが呼び出されるようになります。

これを活用することでカード型UIのカードのリストを表示するFragmentからカードを選択し、別のFragmentに切り替えた時にaddToBackStackを行います。
そして、戻るボタンが押された時にリスト表示に戻ることができます。

ListViewのカスタマイズ

それではフラグメントにカード型UIを作ってみましょう。
カード型UIにはListViewをカスタマイズして、1枚のカードを表示する際に以下の設定を施すことでListViewがカードのように見せかけます。

  • ListViewの設定
  • カスタマイズしたListViewの作成
  • アニメーション設定

まず、ListViewの設定について説明します。
ListViewの標準ではListViewのアイテム間は線が入っており、隙間がありません。
そのためListViewをレイアウトファイルに書く際にの次の設定項目の設定を行います。

  • fadingEdge:縁の色をつけるかどうかを指定する(none:縁なし、horizontal:水平のみ縁あり、vertical:垂直のみ縁あり)
  • dividerHeight:アイテムとアイテムの間の距離を指定する

ここではカードのように表現する必要が有るためfadingEdgeをnoneとし、dividerHeightでカード間の隙間の指定して行います。
その設定をしたものが次のようになります。

    <ListView
            android:id="@+id/list_card"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fadingEdge="none"
            android:divider="#808080"
            android:dividerHeight="8dp"/>

これでListViewのアイテム間に隙間が設けられ、仕切り線も消すことができました。

次はカスタムしたListViewの表示についてです。
カスタムしたListViewを作るにはここのページにて紹介しています。

ここではアイテムのレイアウトは次のようなカード型のレイアウトを作り、ArrayAdapterを継承したカスタムAdapterを用います。

カード

カスタムしたListViewがこれで準備が完了です。

最後にアニメーションを追加します。ListViewのアイテムが表示された時にカスタムしたAdapterのgetViewに注目します。
getViewはリストを操作した時に新しいアイテムが上下どちらかに表示されたときに呼ばれます。
それを機能を利用して、下のアイテムで今まで表示されていないアイテムに限りアニメーションを行うようにすることでカードが追加されたように見せることができます。
まず、アニメーションは次のようにします。

■res/anim/motion.xml

<?xml version="1.0" encoding="utf-8"?>

<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:duration="750"
     android:fillAfter="true">
    <alpha
            android:fromAlpha="0"
            android:toAlpha="1.0"/>
    <translate
            android:fromXDelta="0"
            android:toXDelta="0"
            android:fromYDelta="300"
            android:toYDelta="0"/>
</set>

ここではフェードインと下から上へのアニメーションを750ミリ秒かけてアニメーションを行うアニメーションのリソースになります。
アニメーションの詳しい操作はここでご説明しています。

そして、アニメーションの動作をgetViewに記述します

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View view = convertView;
        if (view == null) {
            view = mInflater.inflate(mListLayoutId, null);
        }
        CardListItem item = (CardListItem) mListItem.get(position);
        if (item != null) {
            // カードのレイアウトに画像や文字をセットする[省略]
        }
        if (mLastAnimationPosition < position) {
            Animation animation = AnimationUtils.loadAnimation(mContext, R.anim.motion);
            view.startAnimation(animation);
            mLastAnimationPosition = position;
        }

        return view;
    }

これでカードの表示ができました。このアニメーションは下から上にアニメーションして追加するだけでなく、右から左へアニメーションすることでも横からカードが追加されたイメージにすることも可能です。