[NeverMind] Internal comments for LayerDrawable.getPadding claim that it is ranked first in the list. If this comment is telling the truth, you can get the right behavior by placing an arbitrary (possibly empty) image in front of your 9 patch in the list.
However, a quick code reading implies that it actually uses the sum of all paddings of elements, which means that there is no way to fix your problem using LayerDrawable by default . A statement implies a solution: implement a subclass of LayerDrawable that overrides "getPadding" to return {0, 0, 0, 0}. You may need to initialize your subclass in code rather than loading an XML layout, but this is not particularly difficult. [/ NeverMind]
Update: The above solution does not work, because the problem is not with the gasket itself, but with the fact that the default implementation sets the boundaries of each image as the sum of the gaskets of the previous images. In other words, it ensures nesting compliance, which is what most people want. The correct solution still overrides LayerDrawable, but instead you replace "onBoundsChange". Full test demo:
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; @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); } } }
using the following 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>
Below is an example screenshot:

Update 2:
As requested, how can you change it to initialize the Selector in code. Replace the initialization of "mCover1" with the following code:
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;
This will be displayed in green in the normal case when the window is focused, but the button is not pressed, red when the button is pressed, and by default (gray) when the window is not focused. (Try dragging the windowshade notification bar to see the window in an unallocated state.)