btn_default_XXX_holo_light.9.png の隙間を取るベストな方法は……

他の方がどうやってるかが気になるんです

# どういうこと

Androidのデフォルトテンプレート (holo lightのやつ) を使ってButtonを配置すると、backgroundに標準で指定されるbtn_default_holo_lightテーマが軒並み隙間を持ってるのです。

![範囲を選択_167.png](https://qiita-image-store.s3.amazonaws.com/0/14365/eea07817-e8c3-0fca-0b33-b78df602dcfa.png)

理由は9patchにその隙間自体が描画されているからです。
marginやpaddingを0dpにしてもこの隙間自体は消えません (後述するマイナスのdpであれば一応消せます)

この隙間を適正な方法で削りたいのですが、9patchなpngは何種類もありまして、面倒だなぁ、削るツール欲しいなぁ、と。

# 一応Pythonでツール作った

今回必要だった機能だけ盛り込んだPythonツールを作ってみました。

https://github.com/dmiyakawa/crop_9patch_space

概要としては以下の通り

* subprocess.PopenでImageMagick関連のツールを叩く
    * convertとmontageを使いました
* 全体を5x5に分解した時の(0,0)(2,0)(4,0)(0,2)(2,2)(4,2)(0,4)(2,4)(4,4)の3x3を使います。
    * 言い換えると、隙間に相当する1・3列と1・3行をふっとばします
    * (0,0)(4,0)(0,4)(4,4)は何となく残しただけ。意味はないです
* 切り取る部分、残す部分のピクセルは各dpi決め打ち
    * 1〜3列、1〜3行のピクセルサイズを固定の辞書構造に詰め込みました
    * PIL使って今回の9patchのエッジのRGB=255,0,0なところを判定すれば自動化はできそうですが、面倒なのでスキップ
* という作業を(mdpi, hdpi, xhdpi, xxhdpi) x (normal, pressed, disabled, focused, disabled_focused) に適用する

ここまでにも若干の紆余曲折はありますが、とりあえずこれで期待する「隙間のない」9patch pngは完成します。

![範囲を選択_166.png](https://qiita-image-store.s3.amazonaws.com/0/14365/9916375c-9a02-a857-c443-be35a87a01ed.png)

なお、どちらかというと、今回はAndroidというよりこのツールを作る上で使ったImageMagick系のツールの挙動を調べるのに四苦八苦しました。

* http://www.imagemagick.org/Usage/crop/
* http://www.imagemagick.org/Usage/montage/

今更だけど、超高機能なのな……

# 作った画像を利用するdrawable xml

```xml
<?xml version="1.0" encoding="utf-8"?>
<!-- Apache2 :-)-->
<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_holo_light_cropped" />
  <item android:state_window_focused="false" android:state_enabled="false"
    android:drawable="@drawable/btn_default_disabled_holo_light_cropped" />
  <item android:state_pressed="true"
    android:drawable="@drawable/btn_default_pressed_holo_light_cropped" />
  <item android:state_focused="true" android:state_enabled="true"
    android:drawable="@drawable/btn_default_focused_holo_light_cropped" />
  <item android:state_enabled="true"
    android:drawable="@drawable/btn_default_normal_holo_light_cropped" />
  <item android:state_focused="true"
    android:drawable="@drawable/btn_default_disabled_focused_holo_light_cropped" />
  <item
    android:drawable="@drawable/btn_default_disabled_holo_light_cropped" />
</selector>
```

ところで、英語としてcroppedは正確ではないのでは……とふと思ったが我慢だ

# でも誰かやってそうじゃね？

最後まで疑問だったのは、この程度のことは誰かやってるんじゃねーか、という話ですね。
この話題ってば非常に古いものなので、ヘタしたらデフォルトのテーマにあったり……見てませんけど :-P

# -4dpとか

paddingでマイナスと値を指定しても一応隙間削れますが、これって良いことだっけ、という別の疑問も。

結構最終手段だった記憶なんですが、なんというか色々知らないことが多いですね。

# ところで赤色による隙間の明示は9patch共通ルール？

9patchではエッジ1pixel領域でメタ情報を詰め込みますが、今回ボタンの画像を見ていて赤色のマーカもついているのに気づきました。

![example_9patch.png](https://qiita-image-store.s3.amazonaws.com/0/14365/d713f2bd-69e2-828f-ac7f-26e33a30c117.png)

こちら、draw9patchやAndroid本体では多分完全に無視されるのですが、何かもっとリッチなツールで自動判定してくれるんでしょうか。


# まとめ

* デフォルトのボタンテーマには隙間があり、paddingやmarginで削ることも出来ないことはないが汚い
* background経由で使われる9patch png向けのツールを作った
* ベストな方法は結局何だったんだろう

# 追記: もらったコメント集

## shapeじゃだめなん？

いいと思います！というか完全に忘れてました。

ただ、ボタンっぽくするのはそれなりに大変かもしれません

## Red Tickはなんか特定のLayout (GridLayout?) で参照されたはず

何かに使われることがあるということはAndroid的に何かサポートしてるってことなのかしら。

そもそもGridLayoutって割と最近ですよねぇ。ということは、割と最近そういうヒューリスティクスを追加したのかしら。

## ```tools:ignore="HardcodedText"``` で警告消せるよ

この記事の初期では以下のような画像を使っていました。各ボタンの警告は```android:text="1"```などと文字列をレイアウトに直書きしていたからです。正しくはstrings.xmlを使います。

![gapped_88buttons.png](https://qiita-image-store.s3.amazonaws.com/0/14365/fb0f32bd-ce4f-feae-7cb7-88111cc8bd13.png)

うっほ！ Android Tools すげぇ！

 * http://tools.android.com/tech-docs/tools-attributes