[NeverMind] LayerDrawable.getPadding の内部コメントは、リストの最初のドローアブルからパディングを取得すると主張しています。このコメントが真実を語っている場合、リスト内の 9 パッチの前に任意の (おそらく空の) イメージを配置することで、必要な動作を得ることができます。
ただし、コードをすばやく読むと、実際にはすべての項目のパディングの合計が使用されていることがわかります。つまり、デフォルトの LayerDrawable を使用して問題を解決する方法がないことを意味します。このステートメントは解決策を暗示しています。「getPadding」をオーバーライドして {0, 0, 0, 0} を返す LayerDrawable のサブクラスを実装します。XML レイアウトをロードするのではなく、コードでサブクラスを初期化する必要がある場合がありますが、これは特に難しいことではありません。[/気にしない]
更新:問題はパディング自体ではないため、上記の解決策は機能しません。デフォルトの実装では、各画像の境界が前の画像のパディングの合計になるように設定されているためです。言い換えれば、ほとんどの人が望んでいるネスティングを強制します。適切な解決策は引き続き LayerDrawable をオーバーライドすることですが、代わりに「onBoundsChange」を置き換えます。テスト済みの完全なデモは次のとおりです。
package com.beekeeper.ninepatchcover;
import android.app.Activity;
import android.graphics.*;
import android.graphics.drawable.*;
import android.os.Bundle;
import android.view.Gravity;
import android.widget.ImageButton;
public class NinePatchCover extends Activity {
private Drawable mCover0;
private Drawable mCover1;
/** Called when the activity is first created. */
@Override public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final Drawable button =
getResources().getDrawable(android.R.drawable.btn_default);
final Bitmap iconBitmap =
BitmapFactory.decodeResource(getResources(),
android.R.drawable.ic_menu_mylocation);
final BitmapDrawable icon = new BitmapDrawable(iconBitmap);
icon.setGravity(Gravity.CENTER);
mCover0 =
getResources().getDrawable(android.R.drawable.title_bar);
mCover1 =
getResources().getDrawable(android.R.drawable.title_bar);
final LayerDrawable unsolved =
new LayerDrawable(new Drawable[]{button, icon, mCover0});
final LayerDrawable solved =
new MyLayerDrawable(new Drawable[]{button, icon, mCover1,}, mCover1);
((ImageButton)findViewById(R.id.uncovered)).setBackgroundDrawable(unsolved);
((ImageButton)findViewById(R.id.covered)).setBackgroundDrawable(solved);
}
class MyLayerDrawable extends LayerDrawable {
Drawable mCover;
public MyLayerDrawable(final Drawable[] layers, final Drawable cover) {
super(layers);
mCover = cover;
}
@Override protected void onBoundsChange(final Rect bounds) {
super.onBoundsChange(bounds);
mCover.setBounds(bounds);
}
}
}
次のlayout/main.xmlを使用
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<ImageButton android:id="@+id/uncovered"
android:layout_width="fill_parent" android:layout_height="wrap_content" />
<ImageButton android:id="@+id/covered"
android:layout_width="fill_parent" android:layout_height="wrap_content" />
</LinearLayout>
サンプルのスクリーンショットは次のとおりです。

更新 2:
要求に応じて、コード内でセレクターを初期化するように変更する方法を次に示します。「mCover1」の初期化を次のコードに置き換えます。
final StateListDrawable sld = new StateListDrawable();
sld.addState(new int[]{android.R.attr.state_pressed},
new ColorDrawable(0xffff0000));
sld.addState(new int[]{android.R.attr.state_window_focused},
new ColorDrawable(0xff00ff00));
sld.addState(new int[]{},
getResources().getDrawable(android.R.drawable.title_bar));
mCover1 = sld;
ウィンドウがフォーカスされているがボタンが押されていない通常の場合は緑、ボタンが押されている場合は赤、ウィンドウがフォーカスされていない場合はデフォルトのドローアブル (灰色) が表示されます。(「windowshade」通知バーを下にドラッグして、ウィンドウがフォーカスされていない状態であることを確認してください。)