Android LayerDrawable包含两个状态的ImageView ListDrawable未在一个图层上绘制已按下状态

Android LayerDrawable包含两个状态的ImageView ListDrawable未在一个图层上绘制已按下状态,android,imageview,android-drawable,Android,Imageview,Android Drawable,我正在尝试使用LayerDrawable作为源来扩展ImageView。每一层由一个StateListDrawable组成,其中一个是ShapeDrawable,另一个是从资源加载的Drawable 在用户按下时,ShapeDrawable从青色逐渐变为白色,可绘制图标从其原始颜色(白色)变为可绘制,并应用颜色过滤器,使其变为相同的青色 图标始终保持不变的原始颜色,但可变形的渐变为白色。我已经从图标中删除了白色状态,并显示了青色,因此我假设这是StateListDrawable的某个地方出现的问

我正在尝试使用LayerDrawable作为源来扩展ImageView。每一层由一个StateListDrawable组成,其中一个是ShapeDrawable,另一个是从资源加载的Drawable

在用户按下时,ShapeDrawable从青色逐渐变为白色,可绘制图标从其原始颜色(白色)变为可绘制,并应用颜色过滤器,使其变为相同的青色

图标始终保持不变的原始颜色,但可变形的渐变为白色。我已经从图标中删除了白色状态,并显示了青色,因此我假设这是StateListDrawable的某个地方出现的问题。我还删除了进入和退出淡出持续时间,但没有成功

代码如下

public class DrawerItemIcon extends ImageView {

    private static final String ITEM_ENABLED_COLOR = "#1ABC9C";

    private int mIconResource;
    private StateListDrawable mCircleDrawable;
    private StateListDrawable mIconDrawable;

    public DrawerItemIcon(Context context, int iconResource) {
        super(context);
        mIconResource = iconResource;
        init();
    }

    private void init() {
        setDuplicateParentStateEnabled(true);
        setImageDrawable(getLayers());
    }

    private LayerDrawable getLayers() {
        Drawable[] layers = new Drawable[2];
        layers[1] = getCircleDrawable();
        layers[0] = getIconDrawable();
        return new LayerDrawable(layers);
    }

    private Drawable getCircleDrawable() {
        mCircleDrawable = new StateListDrawable();
        mCircleDrawable.addState(new int[]{android.R.attr.state_pressed},getPressedShapeCircleDrawable());
        mCircleDrawable.addState(new int[]{android.R.attr.state_enabled}, getEnabledShapeCircleDrawable());
        mCircleDrawable.setEnterFadeDuration(500);
        mCircleDrawable.setExitFadeDuration(500);
        return mCircleDrawable;
    }

    private ShapeDrawable getPressedShapeCircleDrawable() {
        ShapeDrawable bgDrawable = new ShapeDrawable();
        bgDrawable.setShape(new OvalShape());
        bgDrawable.getPaint().setStyle(Paint.Style.STROKE);
        bgDrawable.getPaint().setStrokeWidth(4);
        bgDrawable.getPaint().setColor(Color.WHITE);
        return bgDrawable;
    }

    private ShapeDrawable getEnabledShapeCircleDrawable() {
        ShapeDrawable bgDrawable = new ShapeDrawable();
        bgDrawable.setShape(new OvalShape());
        bgDrawable.getPaint().setStyle(Paint.Style.STROKE);
        bgDrawable.getPaint().setStrokeWidth(4);
        bgDrawable.getPaint().setColor(Color.parseColor(ITEM_ENABLED_COLOR));
        return bgDrawable;
    }

    public Drawable getIconDrawable() {
        mIconDrawable = new StateListDrawable();
        mIconDrawable.addState(new int[]{android.R.attr.state_pressed}, getPressedIconDrawable());
        mIconDrawable.addState(new int[]{android.R.attr.state_enabled}, getEnabledIconDrawable());
        mIconDrawable.setEnterFadeDuration(500);
        mIconDrawable.setExitFadeDuration(500);
        return mIconDrawable;
    }

    private Drawable getPressedIconDrawable() {
        return getResources().getDrawable(mIconResource);
    }

    private Drawable getEnabledIconDrawable() {
        Drawable selectedDrawable = getResources().getDrawable(mIconResource);
        selectedDrawable.setColorFilter(
        new PorterDuffColorFilter(Color.parseColor(ITEM_ENABLED_COLOR), PorterDuff.Mode.MULTIPLY));
        return selectedDrawable;
    }
}

这是因为该可拉伸材料的连续状态。解决这个问题的方法就是在
getEnabledIconDrawable()
方法中添加一个
.mutate()
调用

... getResources().getDrawable(mIconResource).mutate();
有关恒定状态的更多信息,请参见:


其他地方已回答,但将放在此处供将来参考。

您确实应该从可绘制的XML中执行此操作。这将使代码更易于阅读,这可能会使错误更加明显。@alanv我明天将尝试使用XML。尽管此视图仅构成复合视图的一部分。是否有任何原因,从性能角度或其他方面来看,XML比Java更好?@alanv这利用了
ColorFilter
,这在XML中是不可能实现的。瞧,亚历克斯没有想到这一点。我的最低要求是API 14,我认为Tint不在支持库中。@luke william duncan是的,Tint/tintMode从API 1开始就存在了。但是,API 21中添加了不同状态所需的
setImageTintList(ColorStateList)
,您说得对。谢谢您的回复,我明天会检查代码,看看它是否有效。在检查之前,我将此标记为正确答案(我正在处理其他部分,无法应用隐藏)但它仍然不起作用。看看这篇文章,添加以下内容更有意义:selectedDrawable.mutate().setColorFilter(新的PorterDuffColorFilter(Color.parseColor(ITEM_ENABLED_Color),PorterDuff.Mode.MULTIPLY));因为恒定状态肯定是白色的,不是吗?是的,对不起,这就是我的意思。应该多给点背景。在您发布的代码段中,该方法是代码段的
getEnabledCondrawable()
方法,该代码段使用被调用为正确的可绘制对象的
Drawable#mutate()