[NeverMind] LayerDrawable.getPadding 的内部注释声称它从列表中的第一个可绘制对象中获取填充。如果此评论说的是真的,您可以通过在列表中的 9 补丁之前放置任意(可能是空的)图像来获得您想要的行为。
然而,快速阅读代码意味着它实际上使用了所有项目填充的总和,这意味着使用默认的 LayerDrawable无法消除您的问题。该语句暗示了解决方案:实现 LayerDrawable 的子类,它覆盖“getPadding”以返回 {0,0,0,0}。您可能必须在代码中初始化您的子类,而不是通过加载 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);
}
}
}
使用以下布局/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”通知栏以查看处于未聚焦状态的窗口。)