レイアウト(9)-RelativeLayout(相対的位置にウィジェットの配置)をマスターする。
RelativeLayoutは、名前のとおり相対的にウィジェットの配置をおこなうレイアウトである。
このレイアウトを調べていて、相対位置を指定するパラメータがいろいろとあって、違いを把握するのに苦労してしまった。
パラメータはいろいろとあるのだが、「何に対して相対的なのか?」,「上下の位置関係は?」,「左右の位置関係は?」 を、分類してみるとわかりやすくなるように思う。
親ウィジェットに対する相対位置を指定する
以下のパラメータを使って、親ウィジェットに対する相対位置を指定して、ウィジェットの配置をおこなうことができる。
横軸の位置を指定するパラメーター。
- 左側に配置:layout_alignParentLeft
- 中央に配置:layout_centerHorizontal
- 右側に配置:layout_alignParentRight
縦軸の位置を指定するパラメーター。
- 上側に配置:layout_alignParentTop
- 中央に配置:layout_centerVertical
- 下側に配置:layout_alignParentBottom
横軸,縦軸ともに中央に配置するパラメータ。
- 横軸,縦軸ともに中央に配置:layout_centerInParent
これは一つのパラメータで、横軸にcenterHorizontalを縦軸をlayout_centerVertical指定したのと 同じ効果を持つと思われる。
これらのパラメーターには、値としてtrueを指定する。
以下に、これらの各パラメータを組み合わせたxmlレイアウトファイルの例を示す。
リスト1-親ウィジェットに対する相対位置を指定するレイアウトファイルの例(main.xml)
このプログラムを実行すると、以下のような画面が表示される。
子ウィジェットに対する相対位置を指定
他のRelativeLayoutの子ウィジェットに対する相対位置を指定して、ウィジェットの配置をおこなうことができる。
子ウィジェットの外側に配置するパラメータと、内接する位置に配置するパラメータとがある。
パラメーターの値として、対象となる子ウィジェットのIDを指定する。
(1)子ウィジェットの外側(となり)に配置するパラメータ
以下のパラメータを使って、他の子ウィジェットに隣接する位置を指定して、ウィジェットの配置をおこなうことができる。
横軸の位置を指定するパラメーター。
- 左側に配置:layout_toLeftOf
- 右側に配置:layout_toRightOf
縦軸の位置を指定するパラメーター。
- 上側に配置:layout_above
- 下側に配置:layout_below
以下に、これらの各パラメータを組み合わせたxmlレイアウトファイルの例を示す。
リスト2-他の子ウィジェットのとなりに配置するレイアウトファイルの例(main.xml)
このプログラムを実行すると、以下のような画面が表示される。
(2)他の子ウィジェットの内側(内接する位置)に配置するパラメータ
これは、他の子ウィジェットのどちらか片側と同じ位置に、ウィジェットを整列するように配置するパラメータである。
以下のパラメータを使って、他のウィジェットに内接する位置に、ウィジェットの配置をおこなうことができる。
横軸の位置を指定するパラメーター。
- 左側に配置:layout_alignLeft
- 右側に配置:layout_alignTop
縦軸の位置を指定するパラメーター。
- 上側に配置:layout_alignTop
- 下側に配置:layout_alignBottom
以下に、これらの各パラメータを組み合わせたxmlレイアウトファイルの例を示す。
リスト3-他の子ウィジェットに内接する位置に配置するレイアウトファイルの例(main.xml)
このプログラムを実行すると、以下のような画面が表示される。
ウィジェットを等間隔に整列させる
(1)と(2)のパラメータを組み合わせる事によって、 基準のウィジェットに対して等間隔で一列に整列させる事ができる。
以下は、親ウィジェットの中央に配置したボタンを基準に、 下方向に等間隔で縦一列にウィジェットを整列させた例である。
リスト4-他の子ウィジェットを基準に等間隔でウィジェット整列させる(main.xml)
このプログラムを実行すると、以下のような画面が表示される。
layout_alignBaseline-他の子ウィジェットにベースラインの位置を合わせる
layout_alignBaselineを指定すると、 テキストのベースラインの位置を他の子ウィジェットのベースラインの位置に合わせるように、 ウィジェットを配置する事ができる。
以下は、親ウィジェットの中央に配置したボタンを基準に、ベースラインの位置に合わせて左右に ボタンを配置する例である。
リスト5-他の子ウィジェットのベースラインの位置に合わせて左右にボタンを配置する(main.xml)
このプログラムを実行すると、以下のような画面が表示される。
layout_alignWithParentIfMissing
layout_alignWithParentIfMissingパラメータをtrueに指定すると、 相対位置の基準となる他の子ウィジェットが見つからない場合に、親ウィジェットを基準にして配置をおこなう。
以下の例は、リスト3の例を変更して、各ウィジェットにlayout_alignWithParentIfMissingパラメータを 追加するとともに、基準となるウィジェットを非表示(visibility属性をgoneに設定)にした場合の例である。
このプログラムを実行すると、以下のような画面が表示される。
同じように、以下のようにリスト2の例を変更してlayout_alignWithParentIfMissingパラメータ指定すると、 面白いことに、親ウィジェットの外側にはみ出した位置のウィジェットが表示される。
親ウィジェットに対する相対位置と子ウィジェットに対する相対位置の混在指定
以下のように、横軸,縦軸どちらか一方を親ウィジェットに対する相対位置に、 もう片方を子ウィジェットに対する相対位置に指定する事も可能である。
コードを使ってRelativeLayoutを記述する。
以下のレイアウトファイルは、RelativeLayoutの内部にButtonを3個を配置した例である。
これを、レイアウトファイルを使わずにコードで実現すると、以下のようになる。
リスト9-コードを使ってRelativeLayoutを記述(RelativeLayout2Activity.java)
相対位置を指定するパラメータをコードで記述する場合は、 RelativeLayout.LayoutParams#addRuleメソッドを使う。
addRuleメソッドの引数には、xml属性に対応するRelativeLayoutクラスで定義されている定数を指定する。
これまでのまとめも含めて、xml属性に指定するパラメータとaddRuleメソッドの引数に指定する定数の対応表を以下に示す。
対象 | 相対位置 | xml属性 | 定数名 | 定数値 | ||
---|---|---|---|---|---|---|
親 | 横軸,縦軸ともに中央 | layout_centerInParent | CENTER_IN_PARENT | 13 | ||
横軸 | 左 | layout_alignParentLeft | ALIGN_PARENT_LEFT | 9 | ||
横軸 | 中 | layout_centerHorizontal | CENTER_HORIZONTAL | 14 | ||
横軸 | 右 | layout_alignParentRight | ALIGN_PARENT_RIGHT | 11 | ||
縦軸 | 上 | layout_alignParentTop | ALIGN_PARENT_TOP | 10 | ||
縦軸 | 中 | layout_centerVertical | CENTER_VERTICAL | 15 | ||
縦軸 | 下 | layout_alignParentBottom | ALIGN_PARENT_BOTTOM | 12 | ||
子 | 隣接 | 横軸 | 左 | layout_toLeftOf | LEFT_OF | 0 |
横軸 | 右 | layout_toRightOf | RIGHT_OF | 1 | ||
縦軸 | 上 | layout_above | ABOVE | 2 | ||
縦軸 | 下 | layout_below | BELOW | 3 | ||
内接 | 横軸 | 左 | layout_alignLeft | ALIGN_LEFT | 5 | |
横軸 | 右 | layout_alignRight | ALIGN_RIGHT | 7 | ||
縦軸 | 上 | layout_alignTop | ALIGN_TOP | 6 | ||
縦軸 | 下 | layout_alignBottom | ALIGN_BOTTOM | 8 | ||
その他 | 横軸 | 中 | layout_alignBaseline | ALIGN_BASELINE | 4 | |
- | - | layout_alignWithParentIfMissing | 該当なし | - |
layout_alignWithParentIfMissingに対応する定数は存在しない。
layout_alignWithParentIfMissingをコードで指定する場合は、addRuleメソッドを使うのでは無く LayoutParamsクラスのインスタンス変数alignWithParentを、直接操作するようだ。
ウィジェットにどのパラメータが設定されているかは、getRulesメソッドで知る事ができる。
getRulesメソッドは、int型の16個の要素を持つ配列を返す。
パラメータの値がこの配列にどのように格納されているかは、リスト9(19行目のshowRuleメソッドを参照)を実行した結果のLogをみれば、 推察できる。
例えば、button3のlayout_alignLeftパラメータの値が知りたいのであれば、 ALIGN_LEFT定数の値が5なので配列の添え字が5の要素の値を参照すると、 idが2のウィジェット(button2)が指定されていることがわかる。
値をtrueで指定するパラメータの場合は-1(RelativeLayout.TRUE定数で定義されている)が格納される。
RelativeLayout.TRUE定数を使うと、リスト9の23行目のコードは以下のように記述することもできる。
これらの値が0の場合は未指定となる。
button1のlayout_centerInParentと、button2のlayout_centerHorizontal,layout_centerVerticalの 組み合わせは、ともに中央に配置されるが異なる値として格納されている事がわかる。
その他のトピック
RelativeLayoutとGravity
RelativeLayoutにGravity属性を指定する事もできる。以下のように、リスト4のレイアウトファイルのRelativeLayoutにGravity属性を追加する。
Gravityなしの画面とありの画面を比較すると、以下のようになる。
リスト4-Gravityなし | リスト10-Gravity属性を右下に設定 | |
しかし、リスト1の画面のように親ウィジェット内いっぱいにウィジェットが存在する場合にはGravityの効果はなくなるようだ。
ignoreGravity
Gravity属性を無視するウィジェットのIDを指定。
「UIコンポーネント/RelativeLayout - Android Wiki*」を参照。
RelativeLayoutとmargin
RelativeLayout.LayoutParamsクラスもMarginLayoutParamsを継承していて、marginを設定できる。
marginを使うと、ウィジェット間の間隔を調整することができる。
以下は、リスト4のレイアウトファイルを修正して、ウィジェット間の間隔を50ピクセル分広く設定した例である。
リスト11-リスト4のウィジェット間の間隔を50ピクセル分広く設定(main.xml)
このプログラムを実行すると、以下のような画面が表示される。
しかし、以下の例のようにmargin属性の指定の仕方によっては、予想外の配置のされ方をしてしまうようだ。
リスト12-リスト2のレイアウトファイルにmargin属性を追加(main.xml)
このプログラムを実行すると、以下のような画面が表示される。
参考URL
-
UIコンポーネント/RelativeLayout - Android Wiki*
RelativeLayoutのxml属性についてまとめられている。 -
UIコンポーネント/RelativeLayout.LayoutParams - Android Wiki*
RelativeLayoutのLayoutParamsクラスのxml属性についてまとめられている。