I have a bunch of SVG images(5) that I've converted to vector drawables in Android Studio.
I need to hardcode them in my adapter but I can't figure out how to apply.
Using a regular image(a .png or jpg) this is how I would put them in an array.
int[] images = {R.drawable.image_one.png,R.drawable.image_two.png};
and apply to the image like below:
imageView.setImageResource(images[position]);
how can I achieve the same with vector drawables(the extension file ends with .xml)
Using getResources() method as follows
imageView.setImageResource(getResources().getDrawable(R.drawable.image_one));
Both png drawables and vector drawables can be set like this:
Say, on file system your drawable is hello.xml or hello.png
You set it like imageView.setImageResource(R.drawable.hello) in both cases (you don't have to specify extensions)
I would recommend using #DrawableRes annotation next to your type definition, for better compiler checks (#DrawableRes int [] images = ...)
Related
Using a drawable reference to myshape.xml I can set a background like this:
v.setBackgroundResource(R.drawable.myshape);
But what if I want/need to set it all programatically without using drawable reference? Is it possible somehow to supply the <shape/> as a string to set such background without a need of the external resource file drawable\myshape.xml?
You can set the background using a drawable, via the call to v.setBackground() function.
The question should have been, can you create a shape drawable programatically, not via resource.
You can create some shapes programatically, not from a string. Something like this
ShapeDrawable drawable = new ShapeDrawable (new OvalShape());
There are other shapes and options, but you cannot parse a string.
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)
With the new android support update, vector drawables get backward compatibility. I have a vector image with various paths. I want the color of the paths to change on click of a button or programmatically based on an input value. Is it possible to access the name parameter of the vector path? And then change the color.
The color of the whole vector can be changed using setTint.
You have to set up your ImageView in your layout file as this:
<ImageView
android:id="#+id/myImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:tint="#color/my_nice_color"
android:src="#drawable/ic_my_drawable"
android:scaleType="fitCenter" />
Then to change the color of your image:
DrawableCompat.setTint(myImageView.getDrawable(), ContextCompat.getColor(context, R.color.another_nice_color));
Note: myImageView.getDrawable() gives nullpointerexception if the vector drawable is set to the imageView as background.
Use this to change a path color in your vector drawable
VectorChildFinder vector = new VectorChildFinder(this, R.drawable.my_vector, imageView);
VectorDrawableCompat.VFullPath path1 = vector.findPathByName("path1");
path1.setFillColor(Color.RED);
Library is here: https://github.com/devsideal/VectorChildFinder
There are several ways of doing the same stuff, but this works for both Vector Drawables as well as SVG (Local/Network).
imageView.setColorFilter(ContextCompat.getColor(context,
R.color.headPink), android.graphics.PorterDuff.Mode.SRC_IN);
(change R.color.headPink with color of your choice)
You can change the color of individual path at runtime, without using reflection.
VectorMaster introduces dynamic control over vector drawables. Each and every aspect of a vector drawable can be controlled dynamically (via Java instances), using this library.
Just add the following dependency in your app's build.gradle
dependencies {
compile 'com.sdsmdg.harjot:vectormaster:1.0.9'
}
In your case you need a simple color change:
Vector example: your_vector.xml
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:name="outline"
android:pathData="M20.84,4..."
android:strokeColor="#5D5D5D"
android:fillColor="#00000000"
android:strokeWidth="2"/>
XML:
<com.sdsmdg.harjot.vectormaster.VectorMasterView
android:id="#+id/your_vector"
android:layout_width="150dp"
android:layout_height="150dp"
app:vector_src="#drawable/your_drawable" />
Java:
VectorMasterView heartVector = (VectorMasterView)
findViewById(R.id.your_drawable);
// find the correct path using name
PathModel outline = heartVector.getPathModelByName("outline");
// set the stroke color
outline.setStrokeColor(Color.parseColor("#ED4337"));
// set the fill color (if fill color is not set or is TRANSPARENT, then no fill is drawn)
outline.setFillColor(Color.parseColor("#ED4337"));
From: https://github.com/harjot-oberai/VectorMaster, licensed under MIT.
You have now full control over vector drawables.
You can use this method to change color in lower API to change vector color in fragment
int myVectorColor = ContextCompat.getColor(getActivity(), R.color.colorBlack);
myButton.getIcon().setColorFilter(myVectorColor, PorterDuff.Mode.SRC_IN);
in place of getActivity you should use MainActivity.this for changing vector color in activity
Check my answer on this other question: https://stackoverflow.com/a/38418049/1335438.
It is a great idea on how to manage this by using Themes and parameterizing the paths in order to be able to set them dynamically.
As stated by #Eyal in this post
https://stackoverflow.com/a/32007436/4969047
You cannot change the color of individual path at runtime.
Looking at the source code of VectorDrawableCompat, the only method to expose the inner element by name is getTargetByName which is present in inner private state class VectorDrawableCompatState of VectorDrawableCompat.
Since it is a package private (default) - you can't use it (unless you use reflection).
DrawableCompat.setTint(imageView.getDrawable(),ContextCompat.getColor(getApplicationContext(), R.color.colorAccent));
I have an image in a resource file.
Drawable draw = getResources().getDrawable(R.drawable.my_icon);
The image has a transparent background.
Is there a way to programmatically set the background color to the Drawable before using the end product further in my code?
I think Drawing with PorterduffXferMode may help you in your case. This way you can merge two images (your image and a overlay completly in your color you want to replace the transparent pixels with) in many different ways.
Different porterduff modes explaned:
http://www.ibm.com/developerworks/java/library/j-mer0918/
Android example:
http://www.vogella.com/code/ApiDemos/src/com/example/android/apis/graphics/Xfermodes.html
This way you draw the result inside a new Bitmap. (SRC_OVER should work in your case if your image is the src and the background is used as the dst)
setColorFilter() with Porterduff SRC will break the transparent of drawable.
I used this in my code, and it work
disabledIcon = ContextCompat.getDrawable(getContext(), resId);
disabledIcon = DrawableCompat.wrap(disabledIcon);
disabledIcon.mutate(); // to not share its state with any other drawable
DrawableCompat.setTint(disabledIcon, ContextCompat.getColor(getContext(), R.color.button_text_disabled));
I try to display a jpg in android-canvas with a specific transparent color.
It works well with a png and I also know how to convert a jpg to png with java so at the end I have a new png-file on the filesystem.
Now my question:
Is there a way to read a jpg file from the filesystem, set a transparent color at runtime (convert to png) and display the image at runtime ?
additional comment:
I try to do this in my custom view with the ondraw method and drawbitmap. I can't use an imageview. :-(
regards
Andreas
don't make the image transparent but the view.
ImageView myImage = (ImageView) findViewById(R.id.img);
myImage.setAlpha(value);
Value is something between 0 and 255. The lower the number, the more transparent the imageview.