Android 5.0 Lollipop からマテリアルデザインが採用され、Google 製アプリの多くがこれを踏襲するようになりました。サードパーティ製アプリも次第にマテリアルデザインへの移行が進んでいくことでしょう。

 ただ Lollipop がリリースして間もないこともあり、しばらくは Android 4.x が主流でしょう。そこで今回は Android 4.x でマテリアルデザインを取り入れる方法について、その一例を紹介したいと思います。

Playストアアプリのマテリアルデザイン

 Play ストアアプリを起動すると、マテリアルデザインを採用していることがわかります。

 上図では、

  • 画像と他の部分のスクロール量が異なるパララックス効果
  • 画像が画面外へと消えていくのにあわせ、ステータスバー・ツールバーが徐々に出現

 といった表現が用いられています。実は Android 4.x 端末で Play ストアアプリを起動してもマテリアルデザインが適用されているのです。

 今回はこれを再現することを試みました。実際に完成した画面は以下のようになります。

画像のパララックス効果

 パララックス効果は、画像部分のスクロールを他の部分の半分にすることで実現できます。まず次のようなレイアウトのスクロールビューを用意します。

 スクロール量に対し、その半分の移動となるよう、逐次写真の配置を変更するようにします。

画面のスクロール量を取得する

 画面がスクロールされるたびにレイアウトを調整する必要があるため、以下のような継承クラスを作成します。

/**
 * スクロールをコールバックで取得できるScrollView
 */
public class ObservableScrollView extends ScrollView {

    private Callback mCollback;

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        if (mCollback != null){
            mCollback.onScrollChanged(l - oldl, t - oldt);
        }
    }

    public ObservableScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void setCollback(Callback collback) {
        mCollback = collback;
    }

    public static interface Callback {
        public void onScrollChanged(int deltaX, int deltaY);
    }
}

 この継承クラスはスクロールする度にコールバックを行いますので、アクティビティでこのコールバック・インターフェイスを実装し、そこでレイアウトの調整を行います。

    @Override
    public void onScrollChanged(int deltaX, int deltaY) {
        int scrollY = mScrollView.getScrollY();

        // 写真のスクロールを半分にすることでパララックス効果を得る
        mPhotoViewContainer.setTranslationY(scrollY * 0.5f);
    }

ステータスバー、ツールバーの透明度を変化させる

 パララックス効果と同様に、スクロール量にあわせて透明度を変化させます。

    @Override
    public void onScrollChanged(int deltaX, int deltaY) {
        int scrollY = mScrollView.getScrollY();

        // スクロールしただけツールバーを移動させることで常に画面上部に張り付く
        mToolbar.setTranslationY(scrollY);

        // スクロールするほどツールバーの背景を不透明に
        // 写真の高さ分スクロールすると完全に不透明とする
        int alpha = (int)(((float)scrollY / mPhotoHeightPixels) * 255);
        if (alpha < 0) {
            alpha = 0;
        } else if (alpha > 255) {
            alpha = 255;
        }
        mToolbar.getBackground().setAlpha(alpha);
        // ツールバーのタイトル色の透明度を設定
        mToolbar.setTitleTextColor(Color.argb(alpha, 255, 255, 255));
        // ステータスバーの透明度を設定(Android 5.0 以上のみ)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            int color = getWindow().getStatusBarColor();
            getWindow().setStatusBarColor(Color.argb(alpha, Color.red(color), Color.green(color), Color.blue(color)));
        }

        // 写真のスクロールを半分にすることでパララックス効果を得る
        mPhotoViewContainer.setTranslationY(scrollY * 0.5f);
    }

参考資料

 同じくマテリアルデザインが採用されている Google I/O 2014 アプリですが、そのソースコードが公開されています。

 Android 4.x でマテリアルデザインを実現する方法の参考になると思いますので、より深く理解したい方はこちらもぜひ読んでみてください!