Applying Colorfilter to Imageview with Shapeddrawable

Applying ColorFilter to ImageView with ShapedDrawable

Alright, I had a quick play with this and noticed your issue of the circles disappearing. Without you describing what exactly you tried, I assume you haven't tried setting the color filter to the Drawable itself yet? (as opposed to the ImageView, which only seems to work with BitmapDrawables).

The following statements work perfectly fine for an xml-declared ShapeDrawable with white as initial color:

ImageView redCircle = (ImageView) findViewById(R.id.circle_red_imageview);
ImageView greenCircle = (ImageView) findViewById(R.id.circle_green_imageview);
ImageView blueCircle = (ImageView) findViewById(R.id.circle_blue_imageview);

// we can create the color values in different ways:
redCircle.getDrawable().setColorFilter(Color.RED, PorterDuff.Mode.MULTIPLY );
greenCircle.getDrawable().setColorFilter(0xff00ff00, PorterDuff.Mode.MULTIPLY );
blueCircle.getDrawable().setColorFilter(getResources().getColor(R.color.blue), PorterDuff.Mode.MULTIPLY );

The ShapeDrawable for completeness: (I set the size on the ImageView, see below)

<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" >
<solid android:color="@android:color/white" />
</shape>

And one of the ImageViews as example:

<ImageView
android:id="@+id/circle_red_imageview"
android:layout_width="40dp"
android:layout_height="40dp"
android:padding="5dp"
android:src="@drawable/circle_white" />

Visual result:

Screenshot of colored circles

i want to add a color filter to the imageview

The right way to do it was using PorterDuff.Mode.LIGHTEN.

So the updated code will be like:

ImageView iv = (ImageView)findViewById(resIdOfImageToFilter);
iv.setColorFilter(Color.RED, PorterDuff.Mode.LIGHTEN);

Custom ImageView with colorFilter keeps same filter if same drawable is used again

It's likely that the Drawable is being cached, hence the filter is being re-used.
Instead of getDrawable.setColorFilter, try this.setColorFilter, which should set the filter on a copy of the drawable, that is not shared with other instances.

How to change colors of a Drawable in Android?

I was able to do this with the following code, which is taken from an activity (the layout is a very simple one, just containing an ImageView, and is not posted here).

private static final int[] FROM_COLOR = new int[]{49, 179, 110};
private static final int THRESHOLD = 3;

public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.test_colors);

ImageView iv = (ImageView) findViewById(R.id.img);
Drawable d = getResources().getDrawable(RES);
iv.setImageDrawable(adjust(d));
}

private Drawable adjust(Drawable d)
{
int to = Color.RED;

//Need to copy to ensure that the bitmap is mutable.
Bitmap src = ((BitmapDrawable) d).getBitmap();
Bitmap bitmap = src.copy(Bitmap.Config.ARGB_8888, true);
for(int x = 0;x < bitmap.getWidth();x++)
for(int y = 0;y < bitmap.getHeight();y++)
if(match(bitmap.getPixel(x, y)))
bitmap.setPixel(x, y, to);

return new BitmapDrawable(bitmap);
}

private boolean match(int pixel)
{
//There may be a better way to match, but I wanted to do a comparison ignoring
//transparency, so I couldn't just do a direct integer compare.
return Math.abs(Color.red(pixel) - FROM_COLOR[0]) < THRESHOLD &&
Math.abs(Color.green(pixel) - FROM_COLOR[1]) < THRESHOLD &&
Math.abs(Color.blue(pixel) - FROM_COLOR[2]) < THRESHOLD;
}

Can provided Android SDK icons be set with color?

You can indeed use a tint as a way of changing an ImageView's colour, BUT you should be reminded that the android:tint will always be applied on top of the original colour.

as stated by blogger danlew

  • ImageView's tint mixes the tint color with the original asset. What you want is for the tint color to take over entirely; instead it
    applies the tint on top of the existing color. So, for example, if the
    source asset is black, and you want it to be #77FFFFFF (a translucent
    shade of white), you'll actually end up getting that shade of white
    with a black background beneath it.

  • android:tint is limited to ImageView. You want to be able to tint any Drawable in any View.

One possible alternative would be for you to use android ColorFilter

According to the official documentation:

A color filter can be used with a Paint to modify the color of each pixel drawn with that paint. This is an abstract class that should never be used directly.

There are lots of more or less complex things you can do with ColorFilter but how can you apply this then?

One simple example from another so question is:

//White tint
imageView.setColorFilter(Color.argb(255, 255, 255, 255));

or

imageView.setColorFilter(ContextCompat.getColor(context,R.color.COLOR_YOUR_COLOR))

Or a more complete answer here in SO from here

ImageView redCircle = (ImageView) findViewById(R.id.circle_red_imageview);
ImageView greenCircle = (ImageView) findViewById(R.id.circle_green_imageview);
ImageView blueCircle = (ImageView) findViewById(R.id.circle_blue_imageview);

// we can create the color values in different ways:
redCircle.getDrawable().setColorFilter(Color.RED, PorterDuff.Mode.MULTIPLY );
greenCircle.getDrawable().setColorFilter(0xff00ff00, PorterDuff.Mode.MULTIPLY );
blueCircle.getDrawable().setColorFilter(getResources().getColor(R.color.blue), PorterDuff.Mode.MULTIPLY );

You should check these links if you want to learn more

SO - What is the difference between background, backgroundTint, backgroundTintMode attributes in android layout xml?

setColorFilter()

Fast Android asset theming with ColorFilter

SO-Modifying the color of an android drawable

Understanding the Use of ColorMatrix and ColorMatrixColorFilter to Modify a Drawable's Hue

This is what I use for my game. This is the compilation of various part found on various articles on websites. Credits goes to the original author from the @see links.
Note that a lot more can be done with color matrices. Including inverting, etc...

public class ColorFilterGenerator
{
/**
* Creates a HUE ajustment ColorFilter
* @see http://groups.google.com/group/android-developers/browse_thread/thread/9e215c83c3819953
* @see http://gskinner.com/blog/archives/2007/12/colormatrix_cla.html
* @param value degrees to shift the hue.
* @return
*/
public static ColorFilter adjustHue( float value )
{
ColorMatrix cm = new ColorMatrix();

adjustHue(cm, value);

return new ColorMatrixColorFilter(cm);
}

/**
* @see http://groups.google.com/group/android-developers/browse_thread/thread/9e215c83c3819953
* @see http://gskinner.com/blog/archives/2007/12/colormatrix_cla.html
* @param cm
* @param value
*/
public static void adjustHue(ColorMatrix cm, float value)
{
value = cleanValue(value, 180f) / 180f * (float) Math.PI;
if (value == 0)
{
return;
}
float cosVal = (float) Math.cos(value);
float sinVal = (float) Math.sin(value);
float lumR = 0.213f;
float lumG = 0.715f;
float lumB = 0.072f;
float[] mat = new float[]
{
lumR + cosVal * (1 - lumR) + sinVal * (-lumR), lumG + cosVal * (-lumG) + sinVal * (-lumG), lumB + cosVal * (-lumB) + sinVal * (1 - lumB), 0, 0,
lumR + cosVal * (-lumR) + sinVal * (0.143f), lumG + cosVal * (1 - lumG) + sinVal * (0.140f), lumB + cosVal * (-lumB) + sinVal * (-0.283f), 0, 0,
lumR + cosVal * (-lumR) + sinVal * (-(1 - lumR)), lumG + cosVal * (-lumG) + sinVal * (lumG), lumB + cosVal * (1 - lumB) + sinVal * (lumB), 0, 0,
0f, 0f, 0f, 1f, 0f,
0f, 0f, 0f, 0f, 1f };
cm.postConcat(new ColorMatrix(mat));
}

protected static float cleanValue(float p_val, float p_limit)
{
return Math.min(p_limit, Math.max(-p_limit, p_val));
}
}

To complete this I should add an example:

ImageView Sun = (ImageView)findViewById(R.id.sun);
Sun.setColorFilter(ColorFilterGenerator.adjustHue(162)); // 162 degree rotation


Related Topics



Leave a reply



Submit