SetColorFilter () roto en Android 4, trabajando en Android 5

Estoy intentando destellar diversos colores en la pantalla en los intervalos regulares (algunas veces por segundo).

Para cambiar los colores, utilizo Drawable.setColorFilter(int color, Mode mode) en el fondo de mi vista principal:

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

Para propósitos de depuración, agregué otra vista que cambio con View.setBackgroundColor(int color) .

El problema es que las llamadas setColorFilter() están funcionando en Lollipop , pero están rotas en versiones anteriores (específicamente Nexus 7 v4.4.4, Galaxy Nexus v4.2.1).


Llamo el código que cambia de color dentro de un Runnable que es disparado a intervalos regulares por un Handler .

El manejador se llama en todas las plataformas (puedo ver los cambios de fondo debido a las llamadas setBackgroundColor() depuración).

A continuación se muestra el código de color:

 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); } } 

He intentado diferentes valores de PorterDuff.Mode – todavía no puedo conseguir que funcione en Android 4.

¿Qué es diferente entre Android v4 y v5 que cambiaría la forma en que setColorFilter() funciona?

En última instancia, parece que el problema es que KitKat no admite el uso de un ColorFilter (o implícitamente un alfa) en un Drawable que a su vez estará en un StateListDrawable. Mi solución fue usar el mismo código para construir el complejo Drawable y luego convertirlo en un simple 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); } 

Hay un problema en AppCompat con el compuesto Drawable debajo de API 21 que me parece que está relacionado: https://code.google.com/p/android/issues/detail?id=191111

La solución simple no es usar drawables de XML pero crearlos en código y luego aplicar setColorFilter . Es por eso que la solución @Hardeep funcionó.

Fun trivia: En mi caso setColorFilter en XML creado TextView funcionó bien, pero sólo cuando se invocó a través del controlador de clics / retrasado. Cuando se invocó en onCreate / onResume etc no sucedió nada.

Para mí, un ColorFilter no se aplicaría a un elemento de color en un StateListDrawable.

Crear un Drawable para representar ese color y usarlo en su lugar en StateListDrawable vi setColorFilter trabajando en dispositivos pre-Lollipop que probé.

Como una nota lateral, hice un dibujo blanco puro de modo que el color que tiñe se aplicara en la opacidad completa.

¿Has intentado directamente de esta manera ?!

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

Tuve el mismo problema en pre-lollipop, resolví reemplazar:

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

con:

  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} * @param context * @param drawable * @param 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; } 

Recuerdo que esta función funciona en algún lugar de mi proyecto. Prueba por ti mismo.

  • En la barra de navegación Android 4.0 secuestrar el primer evento táctil
  • Problemas al utilizar extensiones en tel: hipervínculos en Android 4
  • SmoothScrollToPosition () sólo se desplaza parcialmente en Android ICS?
  • Android 4.0, el texto en la barra de acción NUNCA muestra
  • Mi aplicación se redujo significativamente en Android 4.0
  • Fácil manera de ocultar la barra del sistema en Android ICS
  • Android Studio: Ice Cream Sandwich (API Nivel 15) La configuración del dispositivo no aparece aunque la imagen del sistema esté instalada
  • ¿Tiene Jellybean 4.2 la intención de conectarse a una VPN ya definida?
  • El widget de la pantalla de inicio de ICS aparece en el dispositivo Pre-ics
  • ADB no reconoce mi Galaxy Nexus - Win7
  • La conexión JDBC de PostgreSQL falla en Android 4.0
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.