更改 NinePatchDrawable 资源颜色



我正在尝试样式微调元素。我为此创建了带有层列表的资源。我在那里使用标准库资源@drawable/abc_spinner_mtrl_am_alpha。这是一个箭头,它总是显示白色。在 android 的 api 版本 21 中,您可以在微调器中设置属性 android:backgroundTint,但我不知道如何在早期版本中执行此操作。

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:bottom="4dp"
        android:left="4dp"
        android:right="4dp"
        android:top="4dp" >
        <shape android:shape="rectangle">
            <stroke
                android:color="#999"
                android:width="1dp" />
            <corners android:radius="2dip" />
            <solid android:color="@android:color/transparent"/>
        </shape>
    </item>
    <item android:id="@+id/notPressedSpinner"
        android:drawable="@drawable/abc_spinner_mtrl_am_alpha"
        android:right="4dp" />
</layer-list>

我尝试使用 setColorFilter 以编程方式更改资源,但它不起作用。

    Drawable abcSpinnerMtrlAmAlpha = mContext.getResources()
            .getDrawable(R.drawable.abc_spinner_mtrl_am_alpha);
    Drawable abcSpinnerMtrlAmAlpha2 = mContext.getResources()
            .getDrawable(R.drawable.abc_spinner_mtrl_am_alpha);
    abcSpinnerMtrlAmAlpha.setColorFilter(mContext.getResources().getColor(R.color.gray_color),
            PorterDuff.Mode.SRC_ATOP);
    abcSpinnerMtrlAmAlpha2.setColorFilter(mContext.getResources().getColor(R.color.green),
            PorterDuff.Mode.SRC_ATOP);
    LayerDrawable x = ((LayerDrawable)mContext.getResources().getDrawable(R.drawable.x));
    LayerDrawable y = ((LayerDrawable)mContext.getResources().getDrawable(R.drawable.y));
    x.setDrawableByLayerId(R.id.notPressedSpinner, abcSpinnerMtrlAmAlpha);
    y.setDrawableByLayerId(R.id.notPressedSpinner, abcSpinnerMtrlAmAlpha2);

我的解决方案

public class StateListDrawableWithTint extends StateListDrawable {
    private ColorStateList mColorStateList;
    private PorterDuff.Mode mFilterMode;
    public StateListDrawableWithTint(Drawable drawable, ColorStateList colorStateList) {
        this(drawable, colorStateList, PorterDuff.Mode.MULTIPLY);
    }
    public StateListDrawableWithTint(Drawable drawable, ColorStateList colorStateList, PorterDuff.Mode filterMode) {
        super();
        mColorStateList = colorStateList;
        mFilterMode = filterMode;
        addState(new int[]{}, drawable);
    }
    @Override
    protected boolean onStateChange(int[] states) {
        if (mColorStateList != null) {
            int stateColor = mColorStateList.getColorForState(states, Color.TRANSPARENT);
            super.setColorFilter(stateColor, mFilterMode);
        }
        return super.onStateChange(states);
    }
}

用:

spinner.setBackgroundDrawable(new StateListDrawableWithTint(
                getResources().getDrawable(R.drawable.sum_currency_spinner),
                getResources().getColorStateList(R.color.sum_currency_spinner),
                PorterDuff.Mode.SRC_ATOP));

可绘制:

        <shape android:shape="rectangle">
            <stroke
                android:color="#999"
                android:width="1.5dp" />
            <corners android:radius="2dip" />
            <solid android:color="@android:color/transparent"/>
        </shape>
    </item>
    <item android:id="@+id/notPressedSpinner"
        android:drawable="@drawable/abc_spinner_mtrl_am_alpha"
        android:right="4dp" />
</layer-list>

颜色状态:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- disabled state -->
    <item android:state_enabled="false" android:color="@color/light_green"/>
    <!-- pressed state -->
    <item android:state_enabled="true" android:state_window_focused="true" android:state_pressed="true" android:color="@color/light_green" />
    <!-- unselected state -->
    <item android:state_enabled="true" android:state_window_focused="true" android:color="@color/gray_color" />
    <!-- dropdown list state -->
    <item android:state_enabled="true" android:state_focused="true" android:color="@color/light_green" />
    <!-- default -->
    <item android:color="@color/light_green" />
</selector>
private static final int[] FROM_COLOR = new int[]{49, 179, 110};
private static final int THRESHOLD = 3;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.test_colors);
ImageView iv = (ImageView) findViewById(R.id.img);
Drawable d = getResources().getDrawable(RES);
iv.setImageDrawable(adjust(d));
}
private Drawable adjust(Drawable d)
{
int to = Color.RED;
//Need to copy to ensure that the bitmap is mutable.
Bitmap src = ((BitmapDrawable) d).getBitmap();
Bitmap bitmap = src.copy(Bitmap.Config.ARGB_8888, true);
for(int x = 0;x < bitmap.getWidth();x++)
    for(int y = 0;y < bitmap.getHeight();y++)
        if(match(bitmap.getPixel(x, y))) 
            bitmap.setPixel(x, y, to);
return new BitmapDrawable(bitmap);
}
private boolean match(int pixel)
{
//There may be a better way to match, but I wanted to do a comparison ignoring
//transparency, so I couldn't just do a direct integer compare.
return Math.abs(Color.red(pixel) - FROM_COLOR[0]) < THRESHOLD &&
    Math.abs(Color.green(pixel) - FROM_COLOR[1]) < THRESHOLD &&
    Math.abs(Color.blue(pixel) - FROM_COLOR[2]) < THRESHOLD;
}

最新更新