2011年3月11日金曜日

Android TableLayoutで列の制御

とりあえず作ったAndroidアプリでつまずいたり調べたりしたことのまとめ2。

Androidアプリを開発していて苦労したことの一つはデザイン周り。なかなか思うように表示できない。layout_widthとかlayout_heightとか、wrap_content、fill_parent、match_parentなどなど。いちいと調べないとすすまない。サンプルなどの勉強ではそのまま真似しててそれほど理解できてなかったってこと。。
このデザイン周りでイライラしたのは、デザインのfill_parentとwrap_contentとが違う位で、アプリケーションがエラーになること。デザイン崩れつつも頑張って表示してくれてもいいじゃん。と思ってしまうのはWebアプリだとブラウザで崩れつつ表示してくれたせいかな。htmlを返すだけで表示はブラウザが行っていたWebアプリと、表示まで行うandroidアプリとの違いか。

で、TableLayoutあたりを少し。

まずは初めに設定したダメパターン。属性は下記の通りで幅と高さとpaddingのみ。ちなみにこれはListViewの一要素のxml。
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent" android:layout_height="fill_parent"
    android:padding="10dip">
    <TableRow>
        <ImageView android:id="@+id/item_img" android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <LinearLayout android:orientation="vertical"
            android:layout_width="fill_parent" android:layout_height="fill_parent"
            android:padding="10dip">
            <TextView android:id="@+id/item_title" android:layout_width="fill_parent"
                android:layout_height="wrap_content" android:scrollHorizontally="true"
                android:textSize="18sp" android:ellipsize="end" />
            <TextView android:id="@+id/item_price" android:layout_width="fill_parent"
                android:layout_height="wrap_content" />
        </LinearLayout>
    </TableRow>
</TableLayout>
これだと、2列目がおかしい。商品名が長いものは、画面をはみでるし、短いものは短いのでフォーカスあたると変な感じ。

まずは、商品名が長い場合にはみ出るのを直す。設定するのは、shrinkColumnsでshrinkしたい(縮めたい)カラムを指定してやる。この例の場合、shrinkしたいのは2列目のLinearLayoutなので(zero-based indexで1列目が0から始まるので)1と指定する。複数指定することも可能で、全部の時は*で指定できるらしい。
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent" android:layout_height="fill_parent"
    android:shrinkColumns="1" android:padding="10dip">
    <TableRow>
        <ImageView android:id="@+id/item_img" android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <LinearLayout android:orientation="vertical"
            android:layout_width="fill_parent" android:layout_height="fill_parent"
            android:padding="10dip">
            <TextView android:id="@+id/item_title" android:layout_width="fill_parent"
                android:layout_height="wrap_content" android:scrollHorizontally="true"
                android:textSize="18sp" android:ellipsize="end" />
            <TextView android:id="@+id/item_price" android:layout_width="fill_parent"
                android:layout_height="wrap_content" />
        </LinearLayout>
    </TableRow>
</TableLayout>
うむ、うまくいった。はみ出ることもない。ちなみに、文字が長いと...と丸められてるのは、商品名のTextViewでandroid:scrollHorizontally="true" android:ellipsize="end"の設定をしているため。shrinkColumnsの設定によるものではない。


今度は短いものを伸ばしたいので、stretchColumnsを設定する。同様に2列目なので1とする。これも*で全列を指定可。全ての列を伸ばすってどういうこと?あとでやってみよう。とりあえずは1を設定する。
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent" android:layout_height="fill_parent"
    android:stretchColumns="1" android:shrinkColumns="1" android:padding="10dip">
    <TableRow>
        <ImageView android:id="@+id/item_img" android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <LinearLayout android:orientation="vertical"
            android:layout_width="fill_parent" android:layout_height="fill_parent"
            android:padding="10dip">
            <TextView android:id="@+id/item_title" android:layout_width="fill_parent"
                android:layout_height="wrap_content" android:scrollHorizontally="true"
                android:textSize="18sp" android:ellipsize="end" />
            <TextView android:id="@+id/item_price" android:layout_width="fill_parent"
                android:layout_height="wrap_content" />
        </LinearLayout>
    </TableRow>
</TableLayout>
てな感じで、stretchColumnsとshrinkColumnsで商品名が長い場合も、短い場合も綺麗に表示することができましたねー。

ちなみに今回使わなかったけど、tablelayoutにはcollapseColumnsってのもあってcollapse(折り畳む) こともできるよう。


オマケ。stretchColumnsとshrinkColumnsともに*指定してみた。
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent" android:layout_height="fill_parent"
    android:stretchColumns="*" android:shrinkColumns="*" android:padding="10dip">
    <TableRow>
        <ImageView android:id="@+id/item_img" android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <LinearLayout android:orientation="vertical"
            android:layout_width="fill_parent" android:layout_height="fill_parent"
            android:padding="10dip">
            <TextView android:id="@+id/item_title" android:layout_width="fill_parent"
                android:layout_height="wrap_content" android:scrollHorizontally="true"
                android:textSize="18sp" android:ellipsize="end" />
            <TextView android:id="@+id/item_price" android:layout_width="fill_parent"
                android:layout_height="wrap_content" />
        </LinearLayout>
    </TableRow>
</TableLayout>
はい、もう意味分かりません。2列目が強いのか1列目の画像が小さくなったり消えたり、2列目のテキストも丸められてたりなかったり。*の使いどきはよくわからないけど、きっとあるんだろう。