我试图定期(每秒几次)在屏幕上闪烁不同的颜色。
要更改颜色,我在主视图的背景上使用Drawable.setColorFilter(int color, Mode mode)
:
myView.getBackground().setColorFilter(Color.RED, PorterDuff.Mode.SRC);
出于调试目的,我添加了另一个使用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()
的工作方式?
答案 0 :(得分:6)
最终,问题似乎是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);
}
答案 1 :(得分:2)
在AppCompat中存在一个问题,我认为API 21下面的化合物Drawable
与之相关:
https://code.google.com/p/android/issues/detail?id=191111
简单的解决方案不是使用XML中的drawable,而是在代码中创建它们然后应用setColorFilter
。这就是@Hardeep解决方案有效的原因。
有趣的琐事:在我的案例setColorFilter
上,XML创建的TextView
drawableLeft
工作正常,但只有通过点击处理程序/延迟调用时才能正常工作。在onCreate
/ onResume
等中调用时,没有任何事情发生。
答案 2 :(得分:1)
我在棒棒糖前有同样的问题,我解决了替换问题:
vBroken.getBackground().setColorFilter(backgroundColor, PorterDuff.Mode.SRC);
使用:
Drawable d = vBroken.getBackground();
d.setColorFilter(backgroundColor, PorterDuff.Mode.MULTIPLY);
vBroken.setBackground(d);
答案 3 :(得分:0)
对我来说,ColorFilter不会应用于StateListDrawable中的颜色项。
创建一个Drawable来表示该颜色,并在StateListDrawable中使用它,看到setColorFilter在我测试的前Lollipop设备上工作。
作为旁注,我制作了一个纯白色的Drawable,以便在完全不透明的情况下应用着色。
答案 4 :(得分:0)
为了在所有Android版本上为所需数量的不同状态绘制drawable,您可以使用此帮助程序类:
@Mock
SingleChronicleQueue chronicle;
@Mock
ExcerptAppender appender;
@Captor
ArgumentCaptor<WriteBytesMarshallable> argumentCaptorLambda;
Persister persister = new Persister();
@Test
public void shouldPersistByteMessage() throws IOException {
persister.write(MESSAGEBYTES);
verify(appender).writeBytes(argumentCaptorLambda.capture());
WriteBytesMarshallable lastValue = argumentCaptorLambda.getValue();
//final byte[] persistedBytes = ?? how to get writeBuffer here ??
//assertThat(readPersistedMessage(persistedBytes), is(MESSAGE));
}
}