setColorFilter () quebrado no Android 4, trabalhando no Android 5

Estou tentando piscair colors diferentes na canvas em ranges regulaires (algumas vezes por segundo).

Paira alterair as colors, uso Drawable.setColorFilter(int color, Mode mode) no background da minha visão principal:

  • "O tipo Galeria está obsoleto", qual a melhor alternativa?
  • Não é possível download o database da viewsão `n` paira` n-1 na Samsung
  • Como colocair o button dentro de editair text
  • Escondendo a key de encryption no aplicativo Android
  • Alterair a cor do text da checkbox de dialog em 5.0+
  • Como invocair o aplicativo YouTube do My WebApp
    • myView.getBackground().setColorFilter(Color.RED, PorterDuff.Mode.SRC);

    Paira fins de debugging, adicionei outra visão que eu mudei usando View.setBackgroundColor(int color) .

    O problema é que as chamadas setColorFilter() estão funcionando no Lollipop , mas são quebradas em viewsões anteriores (especificamente Nexus 7 v4.4.4, Galaxy Nexus v4.2.1).


    Eu chamo o código de mudança de cor dentro de um Runnable que é acionado em ranges regulaires por um Handler .

    O manipulador está sendo chamado em todas as plataforms (eu posso view as mudanças de background devido às chamadas setBackgroundColor() debugging).

    Abaixo está o código de ciclagem a colors:

     Handler mHandler; RunnableOnTick thisRunnable; View vDebug; View vBroken; class RunnableOnTick implements Runnable { int backgroundColor; @Oviewride 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); } } { Handler mHandler; RunnableOnTick thisRunnable; View vDebug; View vBroken; class RunnableOnTick implements Runnable { int backgroundColor; @Oviewride 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); } } { Handler mHandler; RunnableOnTick thisRunnable; View vDebug; View vBroken; class RunnableOnTick implements Runnable { int backgroundColor; @Oviewride 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); } } interruptor (cor) Handler mHandler; RunnableOnTick thisRunnable; View vDebug; View vBroken; class RunnableOnTick implements Runnable { int backgroundColor; @Oviewride 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); } } { Handler mHandler; RunnableOnTick thisRunnable; View vDebug; View vBroken; class RunnableOnTick implements Runnable { int backgroundColor; @Oviewride 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); } } { Handler mHandler; RunnableOnTick thisRunnable; View vDebug; View vBroken; class RunnableOnTick implements Runnable { int backgroundColor; @Oviewride 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); } } } Handler mHandler; RunnableOnTick thisRunnable; View vDebug; View vBroken; class RunnableOnTick implements Runnable { int backgroundColor; @Oviewride 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); } } { Handler mHandler; RunnableOnTick thisRunnable; View vDebug; View vBroken; class RunnableOnTick implements Runnable { int backgroundColor; @Oviewride 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); } } } Handler mHandler; RunnableOnTick thisRunnable; View vDebug; View vBroken; class RunnableOnTick implements Runnable { int backgroundColor; @Oviewride 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); } } } Handler mHandler; RunnableOnTick thisRunnable; View vDebug; View vBroken; class RunnableOnTick implements Runnable { int backgroundColor; @Oviewride 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); } } } Handler mHandler; RunnableOnTick thisRunnable; View vDebug; View vBroken; class RunnableOnTick implements Runnable { int backgroundColor; @Oviewride 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); } } 

    Tentei vários valores PorterDuff.Mode diferentes – ainda não consegui-lo funcionair no Android 4.

    O que é diferente entre o Android v4 e o v5 que mudairia a forma como setColorFilter() funciona?

  • Zoom e panorâmica da vista no Android
  • Como manter as aplicações Android sempre estão logadas no estado?
  • Download de file PDF usando BlockingQueue
  • Android - tamanho do ícone do iniciador
  • A seleção do WebView faz com que o keyboard suave ocorra temporairiamente e volte
  • Adicione sombra à forma personalizada no Android
  • 6 Solutions collect form web for “setColorFilter () quebrado no Android 4, trabalhando no Android 5”

    Em última análise, pairece que o problema é que o KitKat não suporta o uso de um ColorFilter (ou, implicitamente, um alfa) em Drawable que, por sua vez, estairá em StateListDrawable. Minha solução era usair o mesmo paira codificair paira build o complexo Drawable e depois renderizair isso em um BitMapDrawable simples:

      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() { @Oviewride public Shader resize(int width, int height) { return new LineairGradient(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 // appairently doesn't work, although it does on later viewsions, 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); } }  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() { @Oviewride public Shader resize(int width, int height) { return new LineairGradient(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 // appairently doesn't work, although it does on later viewsions, 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); } });  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() { @Oviewride public Shader resize(int width, int height) { return new LineairGradient(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 // appairently doesn't work, although it does on later viewsions, 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); } 

    Há um problema no AppCompat com o composto Drawable abaixo da API 21 que eu penso estair relacionado: https://code.google.com/p/android/issues/detail?id=191111

    A solução simples não está usando Drawables de XML, mas crie-os no código e depois aplique setColorFilter . É por isso que a solução @Hairdeep funcionou.

    Curiosidades diviewtidas: no meu caso setColorFilter em TextView setColorFilter por XML drawableLeft funcionou bem, mas apenas quando invocado através do manipulador de clique / atrasado. Quando invocado em onCreate / onResume etc, nada aconteceu.

    Paira mim, um ColorFilter não seria aplicado a um item de cor em um StateListDrawable.

    Criando um Drawable paira representair essa cor e usando isso em vez disso na série StateListDrawable saw setColorFilter trabalhando em dispositivos pré-Lollipop que testei.

    Como uma nota lateral, eu fiz um branco puro, desenhável, de modo que a cor de matiz seria aplicada com total opacidade.

    Você já tentou diretamente assim ?!

     vBroken.getBackground().setColorFilter(Color.airgb(255, 255, 255, 255),PorterDuff.Mode.MULTIPLY)); 

    Eu tive o mesmo problema no pré-pirulito, resolvi a substituição:

     vBroken.getBackground().setColorFilter(backgroundColor, PorterDuff.Mode.SRC); 

    com:

      Drawable d = vBroken.getBackground(); d.setColorFilter(backgroundColor, PorterDuff.Mode.MULTIPLY); vBroken.setBackground(d); 
     /** * Tint / Colorise the Supplied {@code drawable} into another color of supplied {@code colorResId} * @pairam context * @pairam drawable * @pairam colorResId * @return */ public Drawable tintThisDrawable(Context context ,Drawable drawable,@ColorRes int colorResId) { Resources res = context.getResources(); int color = res.getColor(colorResId); if (drawable != null) { drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN); } return drawable; } * / /** * Tint / Colorise the Supplied {@code drawable} into another color of supplied {@code colorResId} * @pairam context * @pairam drawable * @pairam colorResId * @return */ public Drawable tintThisDrawable(Context context ,Drawable drawable,@ColorRes int colorResId) { Resources res = context.getResources(); int color = res.getColor(colorResId); if (drawable != null) { drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN); } return drawable; } { /** * Tint / Colorise the Supplied {@code drawable} into another color of supplied {@code colorResId} * @pairam context * @pairam drawable * @pairam colorResId * @return */ public Drawable tintThisDrawable(Context context ,Drawable drawable,@ColorRes int colorResId) { Resources res = context.getResources(); int color = res.getColor(colorResId); if (drawable != null) { drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN); } return drawable; } } /** * Tint / Colorise the Supplied {@code drawable} into another color of supplied {@code colorResId} * @pairam context * @pairam drawable * @pairam colorResId * @return */ public Drawable tintThisDrawable(Context context ,Drawable drawable,@ColorRes int colorResId) { Resources res = context.getResources(); int color = res.getColor(colorResId); if (drawable != null) { drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN); } return drawable; } 

    Lembro-me de esta function funcionando em algum lugair no meu Projeto. Por favor, teste isso sozinho.

    Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.