Very common problem with a twist to which I couldn't find a solution for.
I am setting my vector programmatically. I want to be able to change the tint color programmatically too.
Found some solutions such as
Programmatically tint a Support Vector
ImageView iv = ....
Drawable d = VectorDrawableCompat.create(getResources(), R.drawable.ic_exit_to_app_24dp, null);
d = DrawableCompat.wrap(d);
DrawableCompat.setTint(d, headerTitleColor);
iv.setImageDrawable(d);
The main problem comes with
iv.setImageDrawable(d);
I found that prelolipop only accepts setting view's drawable with
iv.setImageResource(int resource)
I couldn't find any solutions for setting it with a drawable file.
Use AppCompatImageView which has setImageDrawable() method.
Related
am using sticker view in my project . it's a library that extend imageView and let you move and rotate image on the screen
https://github.com/nimengbo/StickerView
my problem is that i can't set color filter for images , i have tested every thing
such as
mCurrentView.setColorFilter(getResources().getColor(R.color.red_alpha_95), PorterDuff.Mode.MULTIPLY);
mCurrentView.getDrawable().setColorFilter(getResources().getColor(R.color.red_alpha_95), PorterDuff.Mode.MULTIPLY);
or even making a new drawable from resource and add that drawable to image view ;
i will be greauful if you have any experience with setColorFilter issue or know another lib or approach to move image view on the screen and share it with me
I'm use tint using compat support lib.
int color = ContextCompat.getColor(context, R.color.red_alpha_95);
Drawable drawable = mCurrentView.getDrawable();
Drawable wrap = DrawableCompat.wrap(drawable);
DrawableCompat.setTint(wrap.mutate(), color);
Android SDK provides the following icons.
Is there a way to set a color to those .. and if possible, how to do so?
<ImageView
android:id="#+id/share_button"
style="#style/IconNav"
android:src="#android:drawable/ic_menu_share"/>
<ImageView
android:id="#+id/bookmark_button"
style="#style/IconNav"
android:src="#android:drawable/ic_input_get"/>
UPDATE
After doing a complete refresh of the project, it turns out the tint attribute in Xml did the trick.
For the short answer
.. this is the solution that worked for me - adding the property to the ImageView xml:
android:tint="#color/grass_dark"
The answer from #goldenb is a thorough run through of the different ways to solve for this, so am marking that one as the answer.
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
You can use a bitmap with a tint. Add this to your drawables folder.
ic_input_get_colored.xml :
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="#android:drawable/ic_input_get"
android:tint="#color/yourDesiredColor"/>
Android Studio version 2.1, gradle version 2.1.0, please correct me if you spot any misinterpretations :)
I am confused about support vectors in the support library 23.3.0. Specifically what I would like to do is tint an image button programmatically, whose src is defined is a vector drawable. From what I can tell this is not possible on pre-lollipop now.
I have read several related posts about the changes:
23.2.0 announcement and changes:
As of Android Support Library 23.3.0, support vector drawables can only be loaded via app:srcCompat or setImageResource().
Does the above mean that vector xmls can only be used pre-Lollipop via srcCompat or setImageResource(), and therefore cannot be dynamically tinted?
Here is my basic image button:
<ImageButton
android:id="#+id/nav_header_exit_community_button"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:background="#null"/>
Works on Lollipop and above only:
Drawable bg = ContextCompat.getDrawable(a, R.drawable.ic_exit_to_app_24dp);
DrawableCompat.setTint(bg, headerTitleColor);
exitButton.setImageDrawable(bg);
Attempting this pre-lollipop throws:
android.content.res.Resources$NotFoundException: File res/drawable/ic_exit_to_app_24dp.xml from drawable resource ID #0x7f0200bf
Also works on Lollipop and above only
Drawable bg = ContextCompat.getDrawable(a, R.drawable.ic_exit_to_app_24dp);
DrawableCompat.setTint(bg, headerTitleColor);
exitButton.setImageResource(R.drawable.ic_exit_to_app_24dp);
This throws the same error on pre-Lollipop.
However if I remove vectorDrawables.useSupportLibrary = true as pointed out by Ian Lake here, with the intent of having the build tools auto-generate pngs for pre-Lollipop devices, the pngs do not tint on pre-lollipop, so I'm back to square one.
I have also tried specifying the vector via srcCompat and retrieving it programmatically but I don't think I've been able to achieve that, even though it works on post-Lollipop if the vector is specified using src instead.
So the situation for 23.3.0 seems to be:
Post-Lollipop: src and srcCompat accept vectors, only src can be
retrieved from the view as a drawable for tinting programmatically.
Referencing vectors in code is possible using getDrawable, and they
can be tinted.
Pre-Lollipop: srcCompat only can accept vectors, cannot be retrieved
programmatically from the view for tinting. setImageResource can
accept vectors, but only if vectorDrawables.useSupportLibrary = false, and tinting does not work. Similarly referencing vectors in code is not
possible unless vectorDrawables.useSupportLibrary = false and tinting
does not work.
Working on all versions using pngs:
Drawable bg = ContextCompat.getDrawable(a, R.drawable.ic_nav_exit_community);
DrawableCompat.setTint(bg, headerTitleColor);
exitButton.setImageDrawable(bg);
Addendum:
This technique also works on post-Lollipop, but like the others on pre-Lollipop I get the drawable, but no tinting:
Drawable bg = VectorDrawableCompat.create(a.getResources(), R.drawable.ic_exit_to_app_24dp, null);
DrawableCompat.setTint(bg, headerTitleColor);
exitButton.setImageDrawable(bg);
KIND OF SOLUTION:
Thanks to John's answer so far the only fool-proof way I can come up with to tint a support vector is to set a color filter on it - this means the DrawableCompat.setTint() function is seemingly not functional for me if the drawable in question is a support vector. I'm not sure if this is a legit bug, expected behavior or if I'm just doing something wrong!
Here is the solution I'm going with for the moment:
Drawable bg;
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
bg = VectorDrawableCompat.create(a.getResources(), R.drawable.ic_exit_to_app_24dp, null);
exitButton.setColorFilter(headerTitleColor, PorterDuff.Mode.MULTIPLY);
}
else {
bg = ContextCompat.getDrawable(a, R.drawable.ic_exit_to_app_24dp);
DrawableCompat.setTint(bg, headerTitleColor);
}
exitButton.setImageDrawable(bg);
first of all you should use VectorDrawableCompat#create, once you have your Drawable you have to call DrawableCompat#wrap:
Potentially wrap drawable so that it may be used for tinting across
the different API levels, via the tinting methods in this class.
so your code would look like this:
ImageView iv = ....
Drawable d = VectorDrawableCompat.create(getResources(), R.drawable.ic_exit_to_app_24dp, null);
d = DrawableCompat.wrap(d);
DrawableCompat.setTint(d, headerTitleColor);
iv.setImageDrawable(d);
You can use setColorFilter method of ImageView:
imageView.setColorFilter(headerTitleColor, android.graphics.PorterDuff.Mode.MULTIPLY);
Another handy solution with Kotlin:
fun Context.drawableWithColor(#DrawableRes drawableRes: Int, #ColorInt color: Int): Drawable? {
val pic = ContextCompat.getDrawable(this, drawableRes)
pic?.setColorFilter(color, PorterDuff.Mode.SRC_IN)
return pic
}
Use is as simple as:
val drawable = context.drawableWithColor(R.drawable.your_awesome_drawable, Color.BLUE)
What is the difference between android:setBackground & android:setImageResource when used with an ImageView
I was trying to change the icon of imageButton onclick. when I used:
flashBTN.setImageResource(R.drawable.torch_icon_grey);
I am getting the button covered in grey and the correct drawable doesn't show.
And when I am trying :
flashBTN.setBackground(R.drawable.torch_icon_grey);
I am getting error:setBackground ca't be applied to int
Bonus: How setImageDrawable is difference?
you can read this. I think you are talking about this in xml:
android:background -> A drawable to use as the background, it could be just a color in HEX notation or a drawable.
android:src -> Sets a drawable as the content of this ImageView.
However in java you can use setImageDrawable(Drawable drawable) for setting a drawable as the content of this ImageView.
I'm facing a strange behavior when using ColorFilter with drawables on Lollipop devices.
I'm trying to change the color of some drawables for the whole application.
I used to do that by applying a ColorFilter on it, and then as drawables are sharing their ConstantState, all instances were modified. This is working great on pre lollipop device. However, when running on a lollipop device this seems to be broken and modifications could only be applied to a single instance.
Here is a simple example that works fine on pre lollipop and not after that:
int color = Color.BLUE;
Drawable drawable = getResources().getDrawable(R.drawable.ic_launcher);
drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN);
ImageView iv = new ImageView(this);
iv.setImageResource(R.drawable.ic_launcher);
addContentView(iv, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
On pre lollipop device image is blue, on post lollipop devices, image is unchanged.
And this example is working on both, but is only applied on this instance of that drawable and not when reusing it elsewhere:
int color = Color.BLUE;
Drawable drawable = getResources().getDrawable(R.drawable.ic_launcher);
drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN);
ImageView iv = new ImageView(this);
iv.setImageDrawable(drawable);
addContentView(iv, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT));
As far as I understand, this could be linked to Tint effect on Lollipop applying its own ColorFilter but ImageView here isn't clickable. So I tried applying setTint method on my drawable without success.
So my question is what happened on drawables's constantState in Lollipop release, how can I get my snipnet to work again ?
Thanks.
For ImageView you can change color using below code:
imgView.setColorFilter(iconColor, Mode.MULTIPLY);
It works fine for all versions.