android - setColorFilter() 在 Android 4 上损坏,在 Android 5 上工作

标签 android android-5.0-lollipop android-4.0-ice-cream-sandwich

我试图定期(每秒几次)在屏幕上闪烁不同的颜色。

要更改颜色,我在主视图的背景上使用了 Drawable.setColorFilter(int color, Mode mode):

  • myView.getBackground().setColorFilter(Color.RED, PorterDuff.Mode.SRC);

出于调试目的,我添加了另一个 View ,我使用 View.setBackgroundColor(int color) 进行了更改。

问题setColorFilter() 调用在 Lollipop 上工作,但在以前的版本上损坏(特别是 Nexus 7 v4.4.4、Galaxy Nexus v4.2.1)。


我在 Runnable 中调用颜色更改代码,该代码由 Handler 定期触发。

处理程序在所有平台上都被调用(我可以看到由于调试 setBackgroundColor() 调用而导致的背景变化)。

下面是颜色循环代码:

Handler mHandler;
RunnableOnTick thisRunnable;
View vDebug;
View vBroken;

class RunnableOnTick implements Runnable
{
    int backgroundColor;

    @Override
    public void run()
    {
        color = random.nextInt(2);

        switch (color)
        {
            case 0:
            {
                backgroundColor = Color.RED;
                break;
            }
            case 1:
            {
                backgroundColor = Color.GREEN;
                break;
            }
        }

        // this works on all platforms
        vDebug.setBackgroundColor(backgroundColor);

        // this works only on Lollipop
        vBroken.getBackground().setColorFilter(backgroundColor, PorterDuff.Mode.SRC);
        vBroken.invalidate();

        mHandler.postDelayed(thisRunnable, 100);
    }
}

我尝试了不同的 PorterDuff.Mode 值 - 仍然无法在 Android 4 上运行。

Android v4 和 v5 之间有什么不同会改变 setColorFilter() 的工作方式?

最佳答案

最终,问题似乎是 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);
}

关于android - setColorFilter() 在 Android 4 上损坏,在 Android 5 上工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28717831/

相关文章:

Android 操作栏 : click Up-Button programmatically

android - 隐藏/更改最近应用程序 Android 4.x 中的应用程序屏幕图片

android - ActionBar 导入未被识别

Android - 从选项卡式内容获取对 TabActivity 的引用

android - JSON 不适用于 Android Lollipop

android - Android Lollipop 设备 [Nexus 9 和 nexus 5] 上未显示菜单软键

android - Android Studio类 'FlutterLocationService'不是抽象的,没有实现抽象成员public abstract fun onRequestPermissionsResult

android - 我应该在我的应用程序中显式创建 SQLite 表吗?

Android 如何从 Material Design 文档中实现 Bottom Sheet

ListFragment 中的 Android Actionbar Search 小部件实现