2013年8月31日土曜日

LayerListを利用してカードUIを作る

カードUI(流行ってるの?)を作る手法はいくらか考えられるけど、
  1. Layout.xml上でカード風に見せるViewを定義する
  2. カードUI風の画像を用意する
  3. ShapeDrawableを利用する
  4. カスタムViewを実装してonDrawメソッドを実装する
個人的な考えとしては、1を選択するのは、ないなぁ。

とはいえ、本業がプログラマだと2のように素材をさくっと作ってしまおう!とはいかない。4が恐らく処理速度上でもっとも軽量で、カスタマイズ性も高いものの、ちゃんとしたカスタムViewを作成するには知識がいるので、一番お手軽なのは3の方法でしょうか。

Layer ListでShape Drawableを重ねれば、そこそこな見栄えのカードUIが作れると思います。

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
  <item android:id="@+id/shadow" android:top="1dp" android:left="1dp">
    <shape >
      <solid android:color="#868686" />
    </shape>
  </item>
  <item android:id="@+id/front" android:bottom="1dp" android:right="1dp">
    <shape >
      <gradient android:startColor="#FFFFFF" android:endColor="#EDEDED" android:angle="270"/>
      <stroke android:color="#DBDBDB" android:width="1px" />
    </shape>
  </item>
</layer-list>

xmlに上のように定義して、利用する際はbackgroundのdrawableとして指定するだけ。なお、色はあまり考慮していないのと、State Drawableとして定義していないので、実用はしないでください。


AndroidにはiOSのCore Graphicsのレイヤ操作に相当する機能がないので、もう少しリッチにドロップシャドウを実現したい場合、9patchを用意するか、4を採用して、onDrawメソッドで実装することになります。

---

ところで「9patch画像を作成したら、/drawable/ディレクトリに保存する」とは公式にもそう書いてあるのだけど、「だから9patch画像は一つだけ用意すればいいんだ」という誤解が生じているような気がする。(9patch画像は生の/drawable/に保存する、と書いてあるチュートリアルが異様に多い)

公式ドキュメントが指す/drawable/ディレクトリとは、リソース分岐(/drawable-hdpi/とか)も含めた全体を指していて、9patch画像もピクセル密度に応じて複数の画像を用意する必要がある

このことはAndroid SDKをインストールしたディレクトリの、platforms/android-XX/data/res内を見れば分かります。Androidはボタンなどで9patchを多用しているのですが、ピクセル密度に応じた9patchを用意しているのです。

---

/drawable/に突っ込んだ9patch画像がなぜ問題かというと、実際には/drawable-mdpi/か何かとして認識されているから、例えばNexus 7などの中途半端なピクセル密度で表示されてしまうと、まず画像の本体部分が約1.3倍に引き伸ばされた後、9patchの指定位置ピクセルに補正が掛かるため、ここでズレが生じて破綻するケースがある。

それはまだマシなケースで、画像の拡大縮小の結果、9patchとして違法となった場合、getNinePatchChunk()でnullが返却され、Runtime Exceptionでアプリが強制終了することになる。

もっとも、ピクセル密度に応じて引き伸ばし位置を定義するのは、画像が複雑になると非常に面倒ですし、引き伸ばしだけでタイルパターンには使えないですし、デザイナーの方に9patchの詳細な仕様(Android開発者も知っているか怪しい)を伝える手間もありますし、なかなか難しいところです。

0 件のコメント:

コメントを投稿