Android Tips #34 Android 2.1 から GridLayout を使う
GridLayout が Android 2.1 から使える!
GridLayout は Android 3.0 (APIレベル11) で新たに導入されたレイアウトです。View を Grid 式にレイアウトすることができる、なんで今までなかったの!ってぐらい便利なレイアウトです。このレイアウトですが Support Package v7 を使うと Android 2.1 (APIレベル7) から使うことができます!
Support Package v7 はよく使われる Support Package (プロジェクト作成時につくられるライブラリ) とは導入方法が異なるので、その手順から解説したいと思います。
Support Package v7 の導入方法
1. Support Package をインストールする
まずは Support Package をインストールします。SDK Manager を起動し Support Package にチェックを入れてインストールします。
2. ライブラリプロジェクトをインポートする
次に GridLayout のライブラリプロジェクトをワークスペースにインポートします。メニューより「File > Import...」を選び「Existing Android Code Into Workspace」を選びます。Root Directory は以下を指定します。
${SDK_ROOT}/extras/android/support/v7/gridlayout
SDK フォルダを汚したくない場合は「Copy projects into workspace」にチェックを入れておきます。
追加すると下図のようになります。
3. ライブラリをプロジェクトに追加する
最後に上記ライブラリをプロジェクトに追加して完了です。まずプロジェクトを右クリックし、コンテキストメニューから「Properties」を選択し、プロジェクトプロパティを開きます。
Android 設定の Library で Add ボタンをクリックして、先ほど追加した ライブラリプロジェクトを選択して完了です。
GridLayout の使いかた
レイアウトの定義
まずレイアウトの定義ですが、以下のように GridLayout の定義は <GridLayout> ではなく <android.support.v7.widget.GridLayout> と記述します。また名前空間は http://schemas.android.com/apk/res-auto を指定します。このように指定することでライブラリが複数ある場合にひとつの名前空間に統一することができます。最低限必要なのが行数と列数の指定です。 app:columnCount が行数、 app:rowCount が列数です。
<android.support.v7.widget.GridLayout 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" app:columnCount="4" app:rowCount="3"> </android.support.v7.widget.GridLayout>
まずはシンプルにレイアウトしてみる
ということでまずはシンプルなレイアウト例です。3行、3列のグリッドをレイアウトしてみます。子の View には app:layout_column でどの行に配置するか、 app:layout_row でどの列に配置するか指定しています。行と列は 0 から始まる点に注意してください。
<android.support.v7.widget.GridLayout 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" app:columnCount="3" app:rowCount="3"> <Button android:layout_width="120dp" android:layout_height="80dp" android:text="1" app:layout_column="0" app:layout_row="0" /> <Button android:layout_width="120dp" android:layout_height="80dp" android:text="2" app:layout_column="1" app:layout_row="0" /> <Button android:layout_width="120dp" android:layout_height="80dp" android:text="3" app:layout_column="2" app:layout_row="0" /> <Button android:layout_width="120dp" android:layout_height="80dp" android:text="4" app:layout_column="0" app:layout_row="1" /> <Button android:layout_width="120dp" android:layout_height="80dp" android:text="5" app:layout_column="1" app:layout_row="1" /> <Button android:layout_width="120dp" android:layout_height="80dp" android:text="6" app:layout_column="2" app:layout_row="1" /> <Button android:layout_width="120dp" android:layout_height="80dp" android:text="7" app:layout_column="0" app:layout_row="2" /> <Button android:layout_width="120dp" android:layout_height="80dp" android:text="8" app:layout_column="1" app:layout_row="2" /> <Button android:layout_width="120dp" android:layout_height="80dp" android:text="9" app:layout_column="2" app:layout_row="2" /> </android.support.v7.widget.GridLayout>
こんな感じにレイアウトすることもできます。
<android.support.v7.widget.GridLayout 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" app:columnCount="3" app:rowCount="3"> <Button android:layout_width="120dp" android:layout_height="80dp" android:text="1" app:layout_column="0" app:layout_row="0" /> <Button android:layout_width="120dp" android:layout_height="80dp" android:text="2" app:layout_column="2" app:layout_row="0" /> <Button android:layout_width="120dp" android:layout_height="80dp" android:text="3" app:layout_column="1" app:layout_row="1" /> <Button android:layout_width="120dp" android:layout_height="80dp" android:text="4" app:layout_column="0" app:layout_row="2" /> <Button android:layout_width="120dp" android:layout_height="80dp" android:text="5" app:layout_column="2" app:layout_row="2" /> </android.support.v7.widget.GridLayout>
行または列をまたぐ
行をまたぐには app:layout_columnSpan を使います。指定した数値ぶんの行をまたいでくれます。列の場合は app:layout_rowSpan です。
<android.support.v7.widget.GridLayout 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" app:columnCount="3" app:rowCount="3"> <Button android:layout_width="120dp" android:layout_height="80dp" android:text="1" app:layout_column="0" app:layout_row="0" /> <Button android:layout_width="240dp" android:layout_height="80dp" android:text="2" app:layout_column="1" app:layout_columnSpan="2" app:layout_row="0" /> <Button android:layout_width="120dp" android:layout_height="160dp" android:text="3" app:layout_column="0" app:layout_row="1" app:layout_rowSpan="2" /> <Button android:layout_width="120dp" android:layout_height="80dp" android:text="4" app:layout_column="1" app:layout_row="1" /> <Button android:layout_width="120dp" android:layout_height="80dp" android:text="5" app:layout_column="2" app:layout_row="1" /> <Button android:layout_width="120dp" android:layout_height="80dp" android:text="6" app:layout_column="1" app:layout_row="2" /> <Button android:layout_width="120dp" android:layout_height="80dp" android:text="7" app:layout_column="2" app:layout_row="2" /> </android.support.v7.widget.GridLayout>
View の位置を指定する
子の View を配置する位置を指定するには app:layout_gravity を使います。指定された行・列の中で gravity をとります。
<android.support.v7.widget.GridLayout 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" app:columnCount="3" app:rowCount="3" > <Button android:layout_width="120dp" android:layout_height="80dp" android:text="1" app:layout_column="0" app:layout_columnSpan="2" app:layout_row="0" app:layout_rowSpan="2" app:layout_gravity="center" /> <Button android:layout_width="120dp" android:layout_height="80dp" android:text="2" app:layout_column="2" app:layout_row="0" /> <Button android:layout_width="120dp" android:layout_height="80dp" android:text="3" app:layout_column="2" app:layout_row="1" /> <Button android:layout_width="120dp" android:layout_height="80dp" android:text="4" app:layout_column="0" app:layout_row="2" /> <Button android:layout_width="120dp" android:layout_height="80dp" android:text="5" app:layout_column="1" app:layout_row="2" /> <Button android:layout_width="120dp" android:layout_height="80dp" android:text="6" app:layout_column="2" app:layout_row="2" /> </android.support.v7.widget.GridLayout>
Space で空間をあける
行の高さは保持しておきたいけど View は配置したくないといった、特定の行または列に空間をあけておきたい場合があります。そのときは Space の Support Package v7 版である android.support.v7.widget.Space を使います。以下では2行目に Space を使って空間をあけています。
<android.support.v7.widget.GridLayout 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" app:columnCount="3" app:rowCount="3"> <Button android:layout_width="120dp" android:layout_height="80dp" android:text="1" app:layout_column="0" app:layout_row="0" /> <Button android:layout_width="120dp" android:layout_height="80dp" android:text="2" app:layout_column="1" app:layout_row="0" /> <Button android:layout_width="120dp" android:layout_height="80dp" android:text="3" app:layout_column="2" app:layout_row="0" /> <android.support.v7.widget.Space android:layout_width="360dp" android:layout_height="40dp" app:layout_column="0" app:layout_columnSpan="3" app:layout_row="1" /> <Button android:layout_width="120dp" android:layout_height="80dp" android:text="4" app:layout_column="0" app:layout_row="2" /> <Button android:layout_width="120dp" android:layout_height="80dp" android:text="5" app:layout_column="1" app:layout_row="2" /> <Button android:layout_width="120dp" android:layout_height="80dp" android:text="6" app:layout_column="2" app:layout_row="2" /> </android.support.v7.widget.GridLayout>
Java から動的につくる
最後に Java から動的につくってみたいと思います。LayoutParams を使ってレイアウトを設定し addView() するだけなので特別に難しいことはありません。子 View に対する column と raw の指定には Spec を使って指定します。Spec インスタンスは GridLayout#spec() で取得できます(static メソッド)。任意の Spec を取得し、 LayoutParams.columnSpec と LayoutParams.rowSpec に代入します。いずれもコードヒントで出てくる標準 API のほうを import しないよう注意して実装しましょう。
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); GridLayout layout = new GridLayout(this); layout.setColumnCount(3); layout.setRowCount(3); setContentView(layout); Button button1 = new Button(this); GridLayout.LayoutParams params1 = new GridLayout.LayoutParams(); params1.width = 180; params1.height = 120; params1.columnSpec = GridLayout.spec(0); params1.rowSpec = GridLayout.spec(0); button1.setLayoutParams(params1); button1.setText("1"); layout.addView(button1); Button button2 = new Button(this); GridLayout.LayoutParams params2 = new GridLayout.LayoutParams(); params2.width = 180; params2.height = 120; params2.columnSpec = GridLayout.spec(1); params2.rowSpec = GridLayout.spec(0); button2.setLayoutParams(params2); button2.setText("2"); layout.addView(button2); Button button3 = new Button(this); GridLayout.LayoutParams params3 = new GridLayout.LayoutParams(); params3.width = 180; params3.height = 120; params3.columnSpec = GridLayout.spec(2); params3.rowSpec = GridLayout.spec(0); button3.setLayoutParams(params3); button3.setText("3"); layout.addView(button3); Space space = new Space(this); GridLayout.LayoutParams spaceParams = new GridLayout.LayoutParams(); spaceParams.width = 0; spaceParams.height = 60; spaceParams.columnSpec = GridLayout.spec(0, 3); spaceParams.rowSpec = GridLayout.spec(1); space.setLayoutParams(spaceParams); layout.addView(space); Button button4 = new Button(this); GridLayout.LayoutParams params4 = new GridLayout.LayoutParams(); params4.width = 180; params4.height = 120; params4.columnSpec = GridLayout.spec(0); params4.rowSpec = GridLayout.spec(2); button4.setLayoutParams(params4); button4.setText("4"); layout.addView(button4); Button button5 = new Button(this); GridLayout.LayoutParams params5 = new GridLayout.LayoutParams(); params5.width = 180; params5.height = 120; params5.columnSpec = GridLayout.spec(1); params5.rowSpec = GridLayout.spec(2); button5.setLayoutParams(params5); button5.setText("5"); layout.addView(button5); Button button6 = new Button(this); GridLayout.LayoutParams params6 = new GridLayout.LayoutParams(); params6.width = 180; params6.height = 120; params6.columnSpec = GridLayout.spec(2); params6.rowSpec = GridLayout.spec(2); button6.setLayoutParams(params6); button6.setText("6"); layout.addView(button6); }
「Space で空間をあける」で書いたサンプルと同じレイアウトになるはずです。
まとめ
はじめにも書きましたが、GridLayout は「なんで今までなかったの!?」ってぐらい便利なレイアウトです。いままで LinearLayout で頑張って作っていたかたも多いと思いますが GridLayout を使うことでラクラク実装ができるので、かなりオススメです!今回のサンプルをぜひ参考にして使っていただければと思います。