The Android Studio Vector Assets tools convert vector drawable to PNG-s for devices pre-Lollipop but I get really bad quality PNG-s as you can see here:
What's more is that the button's background solid color is supposed to be this light green that you see on the left but the drawable overwrite it:
<item android:state_checked="true"
android:drawable="@drawable/show">
<shape android:shape="rectangle">
<corners android:bottomRightRadius="8dp"/>
<solid android:color="@color/waveComponentGreen"/>
</shape>
</item>
<item android:state_checked="false"
android:drawable="@drawable/hide">
<shape android:shape="rectangle">
<corners android:bottomRightRadius="8dp"/>
<solid android:color="@color/waveComponentGreen"/>
</shape>
</item>
The xml for the drawable is (the default from the material icons):
<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:fillColor="#FF000000"
android:pathData="M8.59,16.34l4.58,-4.59 -4.58,-4.59L10,5.75l6,6 -6,6z"/>
I wanted also to make the icon appear a bit smaller by tweaking the values and I noticed increasing the viewport dimensions decreases the icon but I'm not sure I understand why.
So: How do I make the icon and the generated PNG appear smaller, less blurry and with the background colour set in the resource file? Thank you.
EDIT: I managed to get the solid colour background with the icon by combining them in a separate xml file with layer-lists:
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape android:shape="rectangle">
<corners android:bottomRightRadius="10dp"/>
<solid android:color="@color/waveComponentGreen"/>
</shape>
</item>
<item android:drawable="@drawable/show"
android:top="10dp"
android:bottom="10dp"
android:left="10dp"
android:right="10dp"
/>
The result is:
I managed to reduce the blurring by increasing the width and height of the vector drawable. However without the android:top|bottom|left|right
tags, the drawable is stretched across the whole area of the button. The second button doesn't need to have a background solid color so I'm not using the layer-list tags => no way to set a top|bottom|left|right
margin for the drawable.
If I reduce the button size what I'm doing is reducing the clickable area of the button.
My updated question is how to set the size of the vector drawable inside a button/toggle button/radio button without reducing the size of the button itself?
UPDATE
I couldn't find a way to resize the vector drawable on pre-API 21 devices. So instead I made the buttons themselves smaller and increased the touch area of each button.
The correct approach to scale any drawable would be to use vectorDrawable.setBounds(left,top,right,bottom)
,
but unfortunately that does not work for vector drawables (why Google ?).
So as a workaround I load my vector drawables , convert them to bitmap drawable and that will allow us to use the setBounds
method on the bitmap drawable. Note that you are scaling bitmaps here , so you can lose some sharpness of the image. I mainly use those methods when I need to use my drawable as a compound drawable of a text view or a button for example.
I ended up writing a helper class that will load a vector drawable set a tint to it and return a bitmap drawable that you can actually scale and tint as you wish. I've tested it for API levels 19 up to 23 , and it works.
Don't forget to use vectorDrawables.useSupportLibrary = true
in your build.gradle.
public class VectorDrawableUtils {
/**
* Gets a Bitmap from provided Vector Drawable image
*
* @param vd VectorDrawable
* @return Bitmap
*/
public static Optional<Bitmap> createBitmapFromVectorDrawable(final @NonNull Drawable vd) {
try {
Bitmap bitmap;
bitmap = Bitmap.createBitmap(vd.getIntrinsicWidth(), vd.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
vd.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
vd.draw(canvas);
return Optional.of(bitmap);
} catch (OutOfMemoryError e) {
Injector.getDependency(getContext(), IEventTracker.class).logHandledException(e);
return Optional.empty();
}
}
/**
* Loads vector drawable and apply tint color on it.
*/
public static Drawable loadVectorDrawableWithTintColor(final @DrawableRes int vdRes,
final @ColorRes int clrRes,final Context context) {
Drawable drawable = ContextCompat.getDrawable(context, vdRes);
DrawableCompat.setTint(drawable, getContext().getResources().getColor(clrRes));
return drawable;
}
/**
* Converts given vector drawable to Bitmap drawable
*/
public static BitmapDrawable convertVectorDrawableToBitmapDrawable(final @NonNull Drawable vd) {
//it is safe to create empty bitmap drawable from null source
return new BitmapDrawable(createBitmapFromVectorDrawable(vd).get());
}
/**
* Loads vector drawable , aplys tint on it and returns a wrapped bitmap drawable.
* Bitmap drawable can be resized using setBounds method (unlike the VectorDrawable)
* @param context Requires view context !
*/
public static Drawable loadVectorDrawableWithTint(
final @DrawableRes int vectorDrawableRes, final @ColorRes int colorRes,final Context context) {
Drawable vd = VectorDrawableUtils.loadVectorDrawableWithTintColor(vectorDrawableRes,
colorRes, context);
final BitmapDrawable bitmapDrawable = VectorDrawableUtils.convertVectorDrawableToBitmapDrawable(vd);
ColorStateList tint = ContextCompat.getColorStateList(context,colorRes);
final Drawable wrappedDrawable = DrawableCompat.wrap(bitmapDrawable);
DrawableCompat.setTintList(wrappedDrawable,tint);
return wrappedDrawable;
}
}
Now I would use this helper class like this :
Drawable bd = VectorDrawableUtils.loadVectorDrawableWithTint(
R.drawable.ic_dropdown, R.color.black,getContext());
bd.setBounds(0, 0, textView.getMeasuredHeight(), textView.getMeasuredHeight());
textView.setCompoundDrawablesWithIntrinsicBounds(null, null, bd, null);
It is important to use a Context of a View or Activity, not the Application context! Hope it will solve your problem, or help someone else. And if someone has a better and cleaner solution, I am interested to know as well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With