第5回は、実際にアプリを作りながら、Material Designをどのように用いるのか説明していきます。アプリ開発を手順ごとに試せる「コードラボ」を活用して、実際のアプリを開発しましょう。
Googleでは、Material ComponentというMaterial Design対応アプリの開発をサポートするライブラリをAndroid、iOS、Web用に提供しています。このMaterial Componentを使うことで、アプリを迅速に作成できます。
Step 1 : 開発環境を用意する
公式IDEのAndroid Studioを利用して、Androidのアプリを開発してみましょう。
Android Studioは開発ツールで、ディスプレイの解像度やCPUが異なるAndoird端末にアプリを最適化できます。コード編集やデバッグ、パフォーマンス解析、柔軟性の高いビルドシステム、素早いデプロイ・ビルドが可能になります。Android Studioは、こちらのサイトからダウンロードしてください。
Step 2 : アプリのベースを作成する
Android Studio では、テンプレートを利用したアプリ製作が可能です。既に、Material Designの要素を含むテンプレートも用意されていますが、今回は何も含まれていない「Empty Activity」というテンプレートを選択します。
テンプレートを選択したら、Android Studio の画面の右上にある、Run (三角形のボタン)を押します。
Android端末をUSBで接続した場合は、ここでアプリがインストールされ、Android上に作成したアプリが表示されます。
このように、”Hello World” が表示されれば、第一段階は完了です。
今回は、最低限のデザインが実装されたアプリを使っていきますので、こちらのサイトからStarterアプリ(zipファイル形式)をダウンロードします(GitHubでクローンする方法もあります)。
zipファイルをダウンロードしたら解凍し、以下のように実行してください。
- Android Studioを起動して、Import Projectを選択
- Starterディレクトリを選択
- OKをクリック
ここまで来たら、先ほどのEmpty Activityの時と同じように、Android端末をUSBケーブルで繋いだ状態で、以下のRun (三角形のボタン) を押してください。
すると以下のような、サンプルアプリがAndroid端末で起動します。
Step 3 : Material Component をプロジェクトに追加する
Starterアプリが起動したら、これをベースにアプリを作っていきます。
まずは、Material Componentsを追加し、 Material Designの各コンポーネントを使えるように準備します。ビルドを自動化するファイルであるGradleファイルを初めに開きます。ライブラリをプロジェクトに追加する場合は、 Gradleファイルに記述していきます。
app/build.gradle
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.android.support:cardview-v7:25.3.1'
compile 'com.android.support:recyclerview-v7:25.3.1'
compile 'com.android.volley:volley:1.0.0'
compile 'com.google.code.gson:gson:2.2.4'
}
Gradleファイルには、こうした記述が既にあるため、このファイルに、
compile 'com.android.support:design:25.3.1'
というコードを記述するとアプリ全体でMaterial Design Componentが使えるようになります。この際、常に最新版のファイルを利用するようを心がけてください。
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.android.support:cardview-v7:25.3.1'
compile 'com.android.support:recyclerview-v7:25.3.1'
compile 'com.android.volley:volley:1.0.0'
compile 'com.google.code.gson:gson:2.2.4'
// この行を追加:
compile 'com.android.support:design:25.3.1'
}
となっていることを確認してください。
Step 4 : Collapsing Toolbarで、折りたたみできるツールバーを作る
Material Designで重要なポイントは、「大きなイメージ画像を効果的にアプリで表現する」ということです。効果的に大きなイメージ画像を表示したい場合、最適なコンポーネントは「Collapsing Toolbar」になります。
Collapsing Toolbarでは、さまざまな異なるViewを管理するLayoutの「Coordinator Layout」をMain Activityに追加します。shr_main.xmlファイルを開いて、FrameLayoutのタグの部分を以下のようなCoordinatorLayoutに置き換えてください。
app/res/layout/shr_main.xml
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- ... -->
</android.support.design.widget.CoordinatorLayout>
CoordinatorLayoutを追加したら、ToolbarにAppBarLayoutとCollapsingToolbarLayoutを追加します。追加する箇所としては、Coordinator Layoutのタグの直下になります。
app/res/layout/shr_main.xml
<!-- ... -->
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="400dp">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar"
style="@style/Widget.Shrine.CollapsingToolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
<!-- Wrap this view: -->
<android.support.v7.widget.Toolbar
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<!-- ... →
上記のコードを記述すると、赤文字のエラーが出ます。
エラーの理由は、Collapsing Toolbarで使用するStyleを読み込めていないから。Styleとは、「Collapsing Toolbarを何色にするのか?」や「マージンを幾つにするのか?」といった装飾部分を指定することです。Styleを指定するためにはstyles.xmlを開き、コメントアウトされている部分を外しましょう。
では、Collapsing Toolbarを追加したところで実際のアプリを見てみましょう。
「Shrine」と書いてある文字がスクロールに合わせて縮小し、上のToolbarに格納されることを確認できます。
ここから、Collapsing Toolbar内にコンテンツを追加していきます。コンテンツを追加するためには、LayoutとActivityのファイルの両方にコードを記述する必要があります。
Layoutに以下を記述します。
app/res/layout/shr_main.xml
<!-- ... -->
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar"
style="@style/Widget.Shrine.CollapsingToolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
<!-- Add this view -->
<com.android.volley.toolbox.NetworkImageView
android:id="@+id/app_bar_image"
style="@style/Widget.Shrine.CollapsingToolbarImage"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="0.75"/>
<android.support.v7.widget.Toolbar
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"/>
</android.support.design.widget.CollapsingToolbarLayout>
<!-- ... -->
次に画像をロードする処理をMainActivity.ktに記載します。
app/java/MainActivity.kt の50行目に
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.shr_main)
setSupportActionBar(app_bar)
val products = readProductsList()
val imageRequester = ImageRequester.getInstance(this)
// Add this code:
val headerProduct = getHeaderProduct(products)
imageRequester.setImageFromUrl(app_bar_image, headerProduct.url)
product_list.setHasFixedSize(true)
product_list.layoutManager = LinearLayoutManager(this)
adapter = ProductAdapter(products, imageRequester)
product_list.adapter = adapter
}
// Add this code as well:
private fun getHeaderProduct(products: List<ProductEntry>): ProductEntry {
if (products.isEmpty()) {
throw IllegalArgumentException("There must be at least one product")
}
for (i in products.indices) {
if ("Perfect Goldfish Bowl" == products[i].title) {
return products[i]
}
}
return products[0]
}
を追加してください。
ここまで終わったら、Runをクリックします。
すると、このようにCollapsing Toolbarの背景に画像が表示されるようになりました。
Step 5 : Bottom Navigation を追加する
Collapsing Toolbarが完成したら、画面間の移動をする上で使う「Bottom Navigation」を追加しましょう。
Bottom NavigationもMaterial Componentのライブラリとして提供されているため、新たにライブラリを追加する必要がありません。Bottom Navigationを利用するには、Layoutファイルに以下のコードを記述します。
app/res/layout/shr_main.xml
<!-- ... -->
</android.support.design.widget.AppBarLayout>
<!-- Add this view -->
<android.support.design.widget.BottomNavigationView
android:id="@+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="#ffffff"
android:theme="@style/ThemeOverlay.Shrine.BottomNavigation"
app:menu="@menu/shr_bottom_navigation"/>
</android.support.design.widget.CoordinatorLayout>
Bottom Navigationは、他のコンテンツより手前に位置する要素なので、shr_main.xmlの最後に上記のコードを記述します。
コードを追加すると、以下のように、Android Studioでエラー部分が赤く表示されます。
これは、Collapsing Toolbarと同じように、Styleの変数が見つからないエラーです。先ほど同じく、styles.xmlにBottom Navigation のスタイルを追加しましょう。
app/res/values/styles.xml
<!-- ... -->
<style name="ThemeOverlay.Shrine.BottomNavigation" parent="">
<item name="colorPrimary">?attr/colorAccent</item>
</style>
</resources>
ただし、Styleを追加しても今度はBottom Navigationに表示するメニューが無いと指摘されます。Bottom Navigationは、画面間を移動するコンポーネントなので、メニューを追加する必要があるからです。
メニューを作成するには、resのディレクトリ内にmenuというディレクトリを作成して、その中に、shr_bottom_navigation.xmlというメニューを表示するxmlを作成します。そして、shr_bottom_navigation.xmlに以下のコードを記述することで、Navigation内にメニューが表示されます。
app/res/menu/shr_bottom_navigation.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/category_clothing"
android:enabled="true"
android:title="@string/shr_category_clothing"
android:icon="@drawable/ic_favorite_vd_theme_24"
app:showAsAction="ifRoom"/>
<item
android:id="@+id/category_home"
android:enabled="true"
android:title="@string/shr_category_home"
android:icon="@drawable/ic_shrine_vd_theme_24"
app:showAsAction="ifRoom"/>
<item
android:id="@+id/category_popsicles"
android:enabled="true"
android:title="@string/shr_category_popsicles"
android:icon="@drawable/ic_shopping_cart_vd_theme_24"
app:showAsAction="ifRoom"/>
</menu>
これで、Runを押すと、次のように表示されます。
ただし、実際にBottom Navigationのメニューをタッチしても、ページが遷移しません。遷移させるためには、MainActivity.ktのファイルにコードを加える必要があります。
今回のケースでは、複数のページを用意せず、Bottom Navigationが押されたら、コンテンツがシャッフルする動作を指定します。その場合、Activityファイルに処理を記述する必要があります。
具体的には、app/java/MainActivity.ktファイルに以下を記述します。
app/java/MainActivity.kt
private fun shuffleProducts() {
val products = readProductsList()
Collections.shuffle(products)
adapter?.setProducts(products)
}
そして、onCreateメソッド内に以下の処理を書きます。
bottom_navigation.setOnNavigationItemSelectedListener {
val layoutManager = product_list.layoutManager as LinearLayoutManager
layoutManager.scrollToPositionWithOffset(0, 0)
shuffleProducts()
true
}
これで、Bottom Navigationをクリックするごとに、コンテンツがシャッフルされます。
Step 6 : レイアウトを調整する
コンテンツを縦に並べる場合、一画面あたりに表示されるコンテンツ数に限界がありますので、レイアウトを調整しましょう。
一つの画面でより多くのコンテンツを見せるためには、2列表示が良いでしょう。そのためには、新しくintegers.xmlというファイルをvalueフォルダ内に作成して、以下のようなコードを記述します。
app/res/values/integers.xml
<resources>
<integer name="shr_column_count">2</integer>
</resources>
この記述によって、2列表示が可能になります。ただ、この記述ではタブレットなどの大きなスクリーンで表示した場合でも、2列で表示されてしまいます。そうした状況を回避する場合は、横幅が480dpよりも大きい場合は3列、900dpよりも大きい場合は6列といったように、その分だけ以下のファイルを追加してください。
app/res/values-w480dp/integers.xml
<resources>
<integer name="shr_column_count">3</integer>
</resources>
app/res/values-w960dp/integers.xml
<resources>
<integer name="shr_column_count">6</integer>
</resources>
このようにファイルを追加すれば、ポートレートモードでは2列表示、ランドスケープモードでは3列といったように、コンテンツを出し分けることが可能になります。
実際に表示する場合は、GridLayout Manager を利用する必要があるため、以下のコードをMainActivity.kt に追加してください。
app/java/MainActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
/* ... */
product_list.setHasFixedSize(true)
product_list.layoutManager = GridLayoutManager(this, resources.getInteger(R.integer.shr_column_count))
adapter = ProductAdapter(products, imageRequester)
product_list.adapter = adapter
/* ... */
}
サンプルアプリを使うことで、Material Design Component を利用して、Android アプリを作る練習ができました。ぜひお試しください。
著者紹介
鈴木 拓生(すずき たくお)
Developer Relations Team Program Manager @ Google
メディア系企業にて、社外のデベロッパーと恊働するプロジェクト等を担当し、 2012 年からはシリコンバレーのスタートアップやインキュベーションに対しての投資も担当。
現在は Google の Developer Relationsチームで主にDesign SprintやMaterial Design周りのコミュニケーションを担当し、デベロッパーやスタートアップのエコシステムの向上を支援