スマートフォンなどでよく見かける、光沢のあるグラデーションを持ったツールバーを画像なしで作成してみる。
Android ではコントロールの描画方法を drawable リソースから指定できる。これは画像と XML に大別できる。
画像はデザインの自由度が高く美しいのだが、解像度 ( ldpi、mdpi、hdpi、…etc ) と引き延ばし ( 詳しくは Draw 9-patch を参照のこと。有志による日本語訳はこちら ) を意識する必要がある。
一方、XML はデザイン指定の方法がかなり限定されるため、希望どおりの描画結果を得るのが難しい。
しかし dp ( または dip。密度非依存ピクセル。詳しくは Supporting Multiple Screens を参照のこと。有志による日本語訳はこちら ) によるサイズ指定と標準で用意されている形状・塗りは解像度に依存しないため、様々な端末への対応が容易になる。
これらの立ち位置は、Web 開発における CSS と画像の関係によく似ている。
Web 開発の場合、描画に関する指定はなるべく CSS でおこない、それが難しい箇所で画像を用いるものだが、
Android でも同様に、アイコンなど複雑な形状を持つものは画像、それ以外は XML というように使い分けることでメンテナンス性が向上する。
さて、本題に入ろう。
まずは光沢グラデーションがどのように構成されているかを画像で表してみる。
下地となるグラデーションがあり、そこへ半分の高さをもつ半透明な陰影を乗せることで、あたかも光沢があるように見える。
これを Android の drawable リソースで再現すると以下のようになる。
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <!-- グラデーション下地 --> <item> <shape android:shape="rectangle"> <gradient android:angle="270" android:startColor="#DDDDDD" android:endColor="#000000" android:type="linear" /> </shape> </item> <!-- グラデーション陰影 --> <item android:top="20dp"> <shape android:shape="rectangle"> <solid android:color="#40000000" /> </shape> </item> </layer-list>
layer-list を利用すると、複数の形状をレイヤーとして重ね合わせた状態を定義できる。各レイヤーは item として表し、その中へ shapr などを入れ子にできる。
この定義は前述の画像で表したように、下地を描き、その上に陰影を重ねている。陰影レイヤーとなる item の android:top が、垂直方向の描画を開始する始点となる。
これは描画領域における相対位置となり、他にも bottom、left、right を指定できる。相対位置ではあるが、感覚としては余白の指定に近い。
位置の指定はディメンション値 ( dp、px、…etc ) となっているので、50% といった割合の定義はできないので注意する。
そのような指定を行いたい場合は、対象となる領域のサイズを決めてから、その割合を固定値として設定する。
今回は領域の高さを 40dp として、その下半分へ陰影が付くように android:top=”20dp” としている。
割合で指定できないのは仕様としてはイマイチな気がする。けれど、Android アプリの画面と GUI の点数はそれほど多くないから、実用上、困ることもないだろう。
これをツールバーの背景に利用するとして、次はその上に乗るボタンを定義してみたい。デザイン的には周辺にくぼみを持つボタンとする。
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <!-- くぼみ --> <item> <shape android:shape="rectangle"> <corners android:bottomRightRadius="4dp" android:bottomLeftRadius="4dp" android:topLeftRadius="4dp" android:topRightRadius="4dp" /> <gradient android:angle="270" android:startColor="#CC222222" android:endColor="#CCEEEEEE" android:type="linear" /> </shape> </item> <!-- グラデーション下地 --> <item android:top="2dp" android:left="2dp" android:right="2dp" android:bottom="2dp"> <shape android:shape="rectangle"> <corners android:bottomRightRadius="4dp" android:bottomLeftRadius="4dp" android:topLeftRadius="4dp" android:topRightRadius="4dp" /> <gradient android:angle="270" android:startColor="#DDDDDD" android:endColor="#222222" android:type="linear" /> </shape> </item> <!-- グラデーション陰影 --> <item android:top="16dp" android:left="2dp" android:right="2dp" android:bottom="2dp"> <shape android:shape="rectangle"> <corners android:bottomRightRadius="0dp" android:bottomLeftRadius="0dp" android:topLeftRadius="4dp" android:topRightRadius="4dp" /> <solid android:color="#40000000" /> </shape> </item> </layer-list>
少し長いが、基本的な考え方はツールバーと同じである。
一つ目のレイヤーでくぼみを定義する。これは上から下へ暗くなるグラデーションとなる。corners の指定はすべての角を丸めるようにする。透過と明るさを変更することで、くぼみ具合を調整できる。
二つ目のレイヤーは、ボタン部分の下地となる。これは前述のツールバー下地と同じような定義となる。
描画の開始をすべて 2dp で指定することにより、描画領域に対して 2dp の余白ができ、この部分にくぼみが描画される。つまりくぼみが枠線的に扱われるため、corners も同様の設定にしておく。
最後のレイヤーで、ボタンの下地に対する陰影を定義する。透過ありの単色塗りである。
これはボタンの下半分に乗せるため、corners の指定は下側だけ丸めるようにする。上も丸めてしまうと、ボタンの中腹にそれが表示されて不自然になるので注意する。
以上でツールバーとボタン用の光沢グラデーション指定ができた。さっそく利用してみよう。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:background="#FF6A00" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <LinearLayout android:background="@drawable/toolbar" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="40dp"> <Button android:background="@drawable/toolbar_button" android:text="TEXT" android:textColor="#FFFFFF" android:textStyle="bold" android:textSize="16dp" android:shadowColor="#000000" android:shadowRadius="2.0" android:shadowDx="1.0" android:shadowDy="2.0" android:paddingLeft="8dp" android:paddingRight="8dp" android:paddingTop="4dp" android:paddingBottom="4dp" android:layout_marginLeft="4dp" android:layout_gravity="center" android:layout_width="wrap_content" android:layout_height="32dp" /> </LinearLayout> </LinearLayout>
10 行目はツールバー、15 行目がボタンの背景指定。これを Android エミュレータで表示すると以下のようになる。
色や透明度を少し変更するだけで、かなり見た目が変わって面白い。
最後に、今回作成したサンプルのプロジェクトを公開しておく
TestGlossyGradient.zip 13.8KB
Android 2.1 update 1 ( API Level 7 ) でビルドし、エミュレータと初代 Xperia ( SO-01B ) にて動作確認をおこなった。