9patchとビューの縮小

AndroidのビューはView#setEnabled(false)により無効イメージを描画することができるが、この無効イメージの高さ(Height)を一定よりも小さくすることで描画に不具合が発生する。

  • 高さ50dpのボタン

setEnabled(true)

setEnabled(false)

  • 高さ40dpのボタン

setEnabled(true)

setEnabled(false)

見て解る通りだが、高さを40dpに設定すると無効時の描画が縞模様になってしまう。
50dpから少しずつサイズを下げて見たが、46dpからこのように描画がおかしく(濃い灰色の領域が閉じない)なることが分った。

この無効時のイメージは元々Viewに設定されているStateListDrawable(XMLではSelector要素+item要素)で管理されているDrawableオブジェクトだ。

    • btn_default.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_window_focused="false" android:state_enabled="true"
        android:drawable="@drawable/btn_default_normal" />
    <item android:state_window_focused="false" android:state_enabled="false"
        android:drawable="@drawable/btn_default_normal_disable" />
    <item android:state_pressed="true" 
        android:drawable="@drawable/btn_default_pressed" />
    <item android:state_focused="true" android:state_enabled="true"
        android:drawable="@drawable/btn_default_selected" />
    <item android:state_enabled="true"
        android:drawable="@drawable/btn_default_normal" />
    <item android:state_focused="true"
        android:drawable="@drawable/btn_default_normal_disable_focused" />
    <item
         android:drawable="@drawable/btn_default_normal_disable" />
</selector>

それぞれのイメージは9-patchと呼ばれており、通常のpngイメージのデータに伸張領域と固定領域の情報を追加したイメージである。

例) ボタン無効時の9-patchイメージ (btn_default_normal_disable.9.png)

アップロードしてしまうと解り難くなってしまうが、上端と左端のドットは伸張できる領域、下端と右端の黒ドットの範囲が固定される領域(コンテンツ)である。

このイメージにより、ボタン等のビューのサイズを拡大してもそこに描画されるボタンの体裁とテキストに影響が出ない作りになっている訳だが、上記のスクリーンショットのようにHeightを小さくすると崩れてしまうので縮小することは想定していないのだろうか。