レイアウト(10)-TableLayout
TableLayoutを使って、htmlのtableタグのように行と列をそろえてウィジェットを配置することができる。
まずは基本形から
TableLayoutの簡単なサンプルとして、表計算ソフトを模して3行3列のEditTextのセルからなるテーブルを表示するxmlレイアウトファイルの例を以下に示す。
リスト1-3行3列のEditTextのセルからなるテーブル(main.xml)
このプログラムを実行すると、以下のような画面が表示される。
レイアウトファイルのTableLayout内に、行を示すTableRowを配置する。
TableRowはhtmlでいえば、trタグに相当するものだと思えばよい。
ここでは、3つのTableRow内にそれぞれEditTextを3つずつ配置しているので、 3行3列のEditTextのセルからなるテーブルが表示される事になる。
上記の例を、xmlレイアウトファイルを使わずにコードで記述すると、以下のようになる。
リスト2-TableLayoutをコードを使って記述する(TableLayout2Activity.java)
同じパターンでTableLayoutにウィジェットを追加していくので、行と列の2重forループを使って3行3列分のTableRowとEditTextを生成している。
TableLayoutに指定するxml属性
TableLayoutクラスには列を制御するために、以下の表のような3つのxml属性が定義されている。
TableLayoutのxml属性 | 設定メソッド | 取得メソッド | 説明 |
---|---|---|---|
shrinkColumns | setColumnShrinkable | isColumnShrinkable | 画面内に収まるように列幅を縮小して表示する。 |
stretchColumns | setColumnStretchable | isColumnStretchable | 画面内に収まるように列幅を広げて表示する。 |
collapseColumns | setColumnCollapsed | isColumnCollapsed | 列を折りたたむ(非表示にする)。 |
後でサンプルコードを示すが、設定メソッドの第1引数には0から始まる列番号を示す引数を指定する。
第2引数には、trueまたはfalseを指定する。
取得メソッドは、引数として列番号を示すint型の数値を指定する。
stretchColumns-列を伸ばす
stretchは筋肉ストレッチのように「伸ばす」という意味である。
リスト1の実行画面のように画面に余白がある場合、stretchColumnsを指定するとTableLayoutが画面の横幅いっぱいに表示されるように、 指定した列を引き伸ばして表示してくれる。
以下はリスト1のmain.xmlを修正して、TableLayoutにstretchColumns属性を指定して列0と2の2つの列幅を広げて表示する例である。
リスト3-stretchColumnsの例(リスト1のmain.xmlを修正・抜粋)
このプログラムを実行すると、以下のような画面が表示される。
リスト1の実行結果と比較すると、列0と列2の列幅が広がってTableLayoutが画面の横幅いっぱいに表示されているのがわかる。
LinearLayoutの場合には余白部分を使うのにlayout_weightを使ったが、TableLayoutの場合にはこのようにstretchColumnsを使う。
次のshrinkColumnsやcollapseColumnsも同じであるが、列番号の指定はカンマで区切って複数指定することができる。
全列を指定する場合は「*」を指定する。
勘違いし易い点として、stretchColumnsを指定すれば常に列幅が広がるわけではない事である。
画面に余白がない場合には、stretchColumnsを指定しても列幅は変化しない。
shrinkColumns-列を縮小する
shrinkというは言葉は「縮小する」という意味である。
TableLayoutのshrinkColumns属性に、縮小したい列の列番号を指定する。
shrinkColumnsを指定すると、stretchColumnsと反対にTableLayoutの列が画面からはみ出している場合に、画面の大きさに収まるように列幅を縮小してくれる。
TableLayoutの列が画面からはみだしていない場合には、shrinkColumnsを指定しても列幅は変化しない。
以下に、shrinkColumnsを指定したxmlレイアウトファイルの例を示す。
リスト4-shrinkColumnsの例(main.xml)
TableLayoutの列が画面からはみだすように、EditTextの表示文字数を多く指定している。
リスト4の4行目のshrinkColumns属性を指定しない場合と、指定した場合の画面の違いを以下に示す。
shrinkColumns属性なし | shrinkColumns属性あり | |
shrinkColumns属性を指定した場合には、指定された列が縮小されて、EditText内の文字が折り返して表示されているのがわかる。
collapseColumns-列の表示,非表示
collapseというは言葉は、日本語訳すると「折りたたむ」という意味である。
collapseColumns属性を指定する事により、指定された列が折りたたまれて非表示となる。
以下は、リスト4のxmlレイアウトファイルを修正して列1を非表示にする例である。
リスト5-collapseColumnsの例(main.xmlの抜粋)
このプログラムを実行すると、以下のような画面が表示される。
列1が非表示になっているのが確認できる。
コードにより列を制御
次のプログラムは、stretchColumns,shrinkColumns,collapseColumnsをコードにより操作して、列の表示を制御する例である。
リスト6-コードにより列を制御(TableLayout3Activity.java)
このプログラムを実行すると、以下のように3行3列にボタンが9個表示される
上段に表示される各列のstretchボタンを押下すると、押された列の列幅が伸縮するのが確認できる。
これはリスト6の33,34行目のコードにより、TableLayoutのstretchColumns属性が反転するためである。
中段のshrinkボタンを押下しても、列幅は変化しない。
shrinkボタンが押下される事で、 53,54行目のコードによりshrinkColumns属性が反転するので 列幅が変化するばずであるが、 TableLayoutが画面からはみだしていないので列幅は変化しないのである。
下段のcollapseボタンを押下すると、押された列は折りたたまれて表示されなくなる。
これは、collapseボタンが押下される事で、72行目のコードにより該当列のcollapseColumns属性がfalseに設定されるためである。
消えた列は、TableLayoutのボタンが表示されていない部分をクリックすると、再び表示されるようになる。
これは、83〜87行目に記述されているTableLayoutのonClickイベントにより、TableLayoutの 各列のcollapseColumns属性をfalseに設定しているためである。
次に、以下のように45行目をコメントに変更、46行目のコメントをはずして、 ボタンの文字数を長くしてTableLayoutが画面からはみだすようにプログラムを変更する。
リスト7-shrinkボタンで列幅が変化するようにリスト6を修正(TableLayout3Activity.java)
今度は、上段のstretchボタンを押下しても各列の列幅は変化しない。
これは、TableLayoutが画面からはみだしていて画面の余白部分が無いためである。
逆に、列が画面からはみだしているので、 中段のshrinkボタンを押下するとshrinkColumns属性が反転する事で列幅が伸縮する。
ボタンをいろいろと操作してみると、どの列のどの属性が変化すると画面がどのように変化するかが確認できる。
ウィジェットに指定するxml属性
TableLayoutには、TableLayoutタグに直接指定するxml属性の他に、TableRowの内部に配置されるウィジェットに対して指定するxml属性も存在する。
TableRowの内のウィジェットに、TableRow.LayoutParamsのxml属性を指定して、ウィジェットの配置を制御する。
TableRow.LayoutParamsのxml属性 | 設定・取得のインスタンス変数 | 説明 |
---|---|---|
layout_column | column | ウィジェットの列位置を指定 |
layout_span | span | ウィジェットが何列分を占めるかを指定 |
layout_column-列位置を指定
ウィジェットにlayout_column属性を指定すると、指定した列位置にウィジェットを配置できる。
列位置は0から始まる事に注意。
以下はリスト1を修正して、列位置の指定を追加する例である。
このプログラムを実行すると、以下のような画面が表示される。
上段の行では、列位置を指定していない。
中段の行では最初に配置するウィジェトの列位置を1,次のウィジェトを列3に配置しているが、最後のウィジェットの列位置は指定されていない。
列位置が指定されていない場合は前のウィジェットの次の列に、表示されるのがわかる。
下段の行では3列目から逆順にウィジェットを配置しようとしているが、 意図に反して、先に配置したウィジェットより前の列位置に配置しようとしても、layout_columnの指定は無視されて次の列位置に配置されてしまう。
これは、先に配置したウィジェットより前の位置に列位置を指定する事ができない事を示している。
layout_span-列を結合
ウィジェットにlayout_span属性を指定すると、複数の列にまたがってウィジェットを配置できる。
layout_span属性はhtmlテーブルのcolspanに相当する。
以下はその例である。
このプログラムを実行すると、以下のような画面が表示される。
最初の行は、layout_columnを指定していないので、1列に1個のウィジェットが配置されている。
次の行では、最初のウィジェットに対してlayout_spanを2に指定してるので、0列目と1列目が結合されている。
さらにその下の行は、2個目のウィジェットに対してlayout_spanを2に指定してるので、1列目と2列目の列が結合されている。
最後の行は、layout_spanに3が指定されているので、3列分の列が結合されている。
行の結合については、後述する。
コードによりlayout_column属性とlayout_span属性を指定
コードを使ってlayout_column属性とlayout_span属性を指定する例を、以下に示す。
リスト10-(TableLayout4Activity.java)
LayoutParamsクラスにはTableLayoutのLayoutParamsとTableRowのLayoutParamsがあるが、 ここで使用する20行目のLayoutParamsはTableRowクラスのLayoutParamsなので、混同しないように注意。
罫線の表示する
テーブルには罫線がつきものだが、 残念ながらTableLayoutには罫線を表示する機能はサポートされていないようだ。
しかし、パディングとマージンを組み合わせて使う事により、見かけ上、罫線が描画されているように見せる事ができる。
パディングとマージンについては「レイアウト(3)-ウィジェットのパディングとマージン - 愚鈍人」を参照。
以下にその例を示す。
このプログラムを実行すると、以下のような画面が表示される。
TableLayoutの背景色に罫線として表示させたい色を指定、左側と上側に1dipのパディングをつける。
テーブル内のセルに配置するTextViewの右側と下側に1dipのマージンをつける。
これにより、あたかも罫線が描画されているように見せている。
行の結合に挑戦
列の結合は、layout_spanを指定する事で実現できた。
列の結合ができるのならば、行の結合(htmlのrowspan)もできるのではないかと当然考えてしまうが、 xml属性では指定することができない。
しかし、まったくできないかというとそうでもない、スマートな解決方法とはいえないがレイアウトを組み合わせることで実現可能である。
リスト1のレイアウトファイルを修正して、セル[1,1]と[2,1]を1つのセルに結合してみる。
xmlレイアウトファイルは以下のようになる。
このプログラムを実行すると、以下のようにセル[1,1]が次の行と結合されて表示される。
ポイントは、結合したい複数の行を一つのTableRowの中に入れる。
TableRowの中で、列ごとに複数行をLinearLayoutで縦に並べる。
LinearLayout内のウィジェットに対して、layout_widthとlayout_heightの指定を省略すると、LinearLayoutさんに怒られるので注意。
行を結合したい列のウィジェットは、layout_heightをfill_parentに指定して、結合する行の高さいっぱいに表示させる。
あやしげなレイアウトであるが、行が結合されているように見えるので、まずは結果オーライ。
レイアウトを組み合わせることで、アイデアしだいでいろんなパターンが考えられそう。
その他いろいろと
次に、TableLayoutとTableRowのリファレンスの「Class Overview」を読んで、知っておいた方が良いと思われる点について述べてみる。TableRowの子ウィジェットのlayout_widthとlayout_height
これまでの例では、TableLayoutのセルに配置するウィジェット(TableRowの子ウィジェット)の layout_widthとlayout_heightの指定を省略してきたが 、 layout_widthとlayout_heightを指定することもできる。
layout_widthとlayout_heightを省略すると、それぞれMATCH_PARENT(FILL_PARENTと同じ)とWRAP_CONTENTとなる。
同じ列の異なる行に対して、異なるlayout_widthを指定すると、ウィジェットの幅は大きい方に合わせられる。
同様に、同じ行の異なる列に対して異なるlayout_heightを指定すると、 ウィジェットの高さは異なる高さになるが、行全体の高さは大きい方に合わせられる。
以下の例は、その様子を示している。
リスト13-TableRowの個々の子ウィジェットに異なる幅と高さを指定(main.xml)
このプログラムを実行すると、以下のような画面が表示される。
最初の行と次の行の各列のEditTextの幅を異なる値に指定しているにもかかわらず、 各列のEditTextの幅が同じになっているのがわかる。
また、EditTextの高さを異なる値に指定しているので、高さについてはそれが反映されているが、 行全体の高さはそろえられているのが確認できる。
layout_widthとlayout_heightを数値で指定しても、shrinkColumnsやstrechColumnsを指定すると 列幅は画面内に収まるように調整される。
TableLayoutの子ウィジェットのlayout_widthとlayout_height
これまで、TableLayoutの子ウィジェットにはTableRowを指定してきたが、他のウィジェットも指定できる。
TableLayoutの子ウィジェットは、layout_widthを指定できない(指定しても無視される。)
layout_widthは、常にMATCH_PARENになる。
TableRowに、layout_widthとlayout_heightを指定する事はできない(無視される)。
TableLayoutの子ウィジェットがTableRow以外の場合、layout_heightは指定できる。
layout_heightは未指定時 、WRAP_CONTENTとなる。
上記の点を利用して、TableLayoutの子ウィジェットにTableRow以外のウィジェットを配置すると、 TableRowの列幅の制限を超えて、ウィジェットを配置する事ができる。
以下はその例である。
リスト14-列幅の制限を超えてウィジェットを配置(main.xml)
このプログラムを実行すると、以下のような画面が表示される。
TableLayoutの真ん中の行の2つのEditTextが、TableRowの列幅の制限を超えて配置されているのがわかる。
参考URL
-
2.3 テーブルレイアウト - ソフトウェア技術ドキュメントを勝手に翻訳
TableLayoutにViewウィジェットを利用して線を描画する方法が興味深い。