首页 文章

setColorFilter似乎不适用于kitkat

提问于
浏览
3

我正在尝试使用 setColorFilter 为图形着色 . 以下代码似乎在棒棒糖上工作正常,但它似乎对kitkat没有影响,图标以其原始颜色呈现:

Drawable icon = ContextCompat.getDrawable(context, R.drawable.ic_chat_button).mutate();
icon.setColorFilter(context.getResources().getColor(R.color.control_tint_color), PorterDuff.Mode.SRC_ATOP);
icon.invalidateSelf();

mutateinvalidateSelf 呼叫试图弄清楚发生了什么 .

FWIW,我在_912447中使用drawable作为 LayerDrawable 的一部分,它被用作按钮的背景或用作 ImageView 的drawable . 结果是一致的(即,kitkat上的错误) . 我也尝试将图标drawable直接放入 StateListDrawable ,但没有改变行为 . 在所有情况下,它在棒棒糖上工作正常,但不适用于kitkat .

作为一个实验,我从 StateListDrawable 中取出了有色的 Drawable 而不是 LayerDrawable ,它按预期工作 . 显然有 StateListDrawableStateListDrawable 实现阻止它工作,这在以后的版本中得到了补救 .

2 回答

  • 4

    最终,问题似乎是KitKat不支持在 Drawable 上使用 ColorFilter (或隐式地使用alpha),而 Drawable 又将在 StateListDrawable 中 . 我的解决方案是使用相同的代码来构造复杂的 Drawable ,然后将其渲染成一个简单的 BitMapDrawable

    static Drawable createDrawable(Context context, int color, boolean disabled) {
        OvalShape oShape = new OvalShape();
        ShapeDrawable background = new ShapeDrawable(oShape);
        background.getPaint().setColor(color);
    
        ShapeDrawable shader = new ShapeDrawable(oShape);
        shader.setShaderFactory(new ShapeDrawable.ShaderFactory() {
            @Override
            public Shader resize(int width, int height) {
                return new LinearGradient(0, 0, 0, height,
                        new int[]{
                                Color.WHITE,
                                Color.GRAY,
                                Color.DKGRAY,
                                Color.BLACK
                        }, null, Shader.TileMode.REPEAT);
            }
        });
    
        Drawable icon = ContextCompat.getDrawable(context, R.drawable.ic_chat_button).mutate();
        icon.setColorFilter(context.getResources().getColor(R.color.control_tint_color), PorterDuff.Mode.SRC_IN);
    
        Drawable layer = new LayerDrawable(new Drawable[]{ shader, background, icon });
        layer.setAlpha(disabled ? 128 : 255);
    
        // Note that on KitKat, setting a ColorFilter on a Drawable contained in a StateListDrawable
        //  apparently doesn't work, although it does on later versions, so we have to render the colored
        //  bitmap into a BitmapDrawable and then put that into the StateListDrawable
        Bitmap bitmap = Bitmap.createBitmap(icon.getIntrinsicWidth(), icon.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
    
        layer.setBounds(0, 0, layer.getIntrinsicWidth(), layer.getIntrinsicHeight());
        layer.draw(canvas);
    
        return new BitmapDrawable(context.getResources(), bitmap);
    }
    
  • 4

    而不是将着色附加到类似"disabled"状态的东西(如在接受的答案中),我发现通过专注于重新着色并让我的用法利用如何在_912462中包含现在着色的图像来更简单 . (还有,我是've tried to translate from the Xamarin C# I' m使用,但下面的代码可能无法正确编译为Java)

    static Drawable recolorDrawable(Drawable icon, int toColor)
    {
        Bitmap bitmap = Bitmap.createBitmap(icon.getIntrinsicWidth(), icon.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
        Canvas myCanvas = new Canvas(bitmap);
    
        icon.setColorFilter(toColor, PorterDuff.Mode.SRC_IN);
        icon.setBounds(0, 0, icon.getIntrinsicWidth(), icon.getIntrinsicHeight());
        icon.draw(myCanvas);
    
        return new BitmapDrawable(context.getResources(), bitmap);
    }
    

    最后,公平地对待接受的答案,我对Android开发很陌生,可以感谢他在展示我需要的部分之前简化它们 .

相关问题