How to set the size of a vector vector inside a button on Android?

Android Studio Vector Assets tools convert the vector transferred to PNG files for pre-Lollipop devices, but I get very poor PNG-s quality, as you can see here:

Converted vector to PNG

What else does it mean that the main background color of the button should be so light green that you see on the left, and the popped one will 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> 

xml for drawable (default from 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 also wanted the icon to look a little smaller by changing the values, and I noticed that increasing the viewport size reduces the icon, but I'm not sure I understand why.

So: how to make the icon and the generated PNG smaller, less blurry and with the background color set in the resource file? Thanks.

EDIT : I managed to get a solid background color using the icon, combining them into a separate XML file with lists of layers:

 <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" /> 

Result:

The result of some tweaking

I managed to reduce the blur by increasing the width and height of the vector. However, without the android:top|bottom|left|right tags android:top|bottom|left|right stretchable is stretched across the entire area of ​​the button. The second button should not have a solid background color, so I do not use tags from the list of layers => there is no way to set the marker top|bottom|left|right to draw.
If I reduce the size of the button, what I do is reduce the button click area.

My updated question is how to set the size of a vector that can be cut inside a button / switch / switch without reducing the size of the button itself?

UPDATE
I could not find a way to resize the vector that could be used on devices prior to API 21. Therefore, instead, I made the buttons themselves smaller and increased the touch area of ​​each button.

+6
source share
2 answers

The correct approach to scaling any available options is to use vectorDrawable.setBounds(left,top,right,bottom) , but unfortunately this does not work for vector drawings (why Google?).

So, as a workaround, I upload my vector drawings, converting them to a raster plant, and this will allow us to use the setBounds method to draw a bitmap. Note that you are scaling bitmaps here so you can lose some sharpness in the image. I mainly use these methods when I need to use my drawable as part of a text view or button, for example.

In the end, I wrote a helper class that will load a vector set that sets the hue for it and return a bitmap that you can actually scale and shade as you wish. I tested it for API levels from 19 to 23 and it works.

Remember to use vectorDrawables.useSupportLibrary = true in 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 as follows:

  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 the context of the view or action, not the context of the application! Hope it solves your problem or helps someone else. And if someone has a better and cleaner solution, I am also interested to know.

+10
source

MyTextView Class:

 public class MyTextView extends AppCompatTextView { public MyTextView(Context context) { super(context); } public MyTextView(Context context, AttributeSet attrs) { super(context, attrs); initAttrs(context, attrs); } public MyTextView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initAttrs(context, attrs); } void initAttrs(Context context, AttributeSet attrs) { if (attrs != null) { TypedArray attributeArray = context.obtainStyledAttributes( attrs, R.styleable.MyTextView); int defaultWidthHeight = 0; int widthHeight = 0; Drawable drawableLeft = null; Drawable drawableStart = null; Drawable drawableRight = null; Drawable drawableEnd = null; Drawable drawableBottom = null; Drawable drawableTop = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { drawableLeft = attributeArray.getDrawable(R.styleable.MyTextView_drawableLeftCompatTextView); drawableStart = attributeArray.getDrawable(R.styleable.MyTextView_drawableStartCompatTextView); drawableRight = attributeArray.getDrawable(R.styleable.MyTextView_drawableRightCompatTextView); drawableEnd = attributeArray.getDrawable(R.styleable.MyTextView_drawableEndCompatTextView); drawableBottom = attributeArray.getDrawable(R.styleable.MyTextView_drawableBottomCompatTextView); drawableTop = attributeArray.getDrawable(R.styleable.MyTextView_drawableTopCompatTextView); } else { final int drawableLeftId = attributeArray.getResourceId(R.styleable.MyTextView_drawableLeftCompatTextView, -1); final int drawableStartId = attributeArray.getResourceId(R.styleable.MyTextView_drawableStartCompatTextView, -1); final int drawableRightId = attributeArray.getResourceId(R.styleable.MyTextView_drawableRightCompatTextView, -1); final int drawableEndId = attributeArray.getResourceId(R.styleable.MyTextView_drawableEndCompatTextView, -1); final int drawableBottomId = attributeArray.getResourceId(R.styleable.MyTextView_drawableBottomCompatTextView, -1); final int drawableTopId = attributeArray.getResourceId(R.styleable.MyTextView_drawableTopCompatTextView, -1); if (drawableLeftId != -1) drawableLeft = AppCompatResources.getDrawable(context, drawableLeftId); if(drawableStartId != -1) drawableStart = AppCompatResources.getDrawable(context, drawableStartId); if (drawableRightId != -1) drawableRight = AppCompatResources.getDrawable(context, drawableRightId); if(drawableEndId != -1) drawableEnd = AppCompatResources.getDrawable(context, drawableEndId); if (drawableBottomId != -1) drawableBottom = AppCompatResources.getDrawable(context, drawableBottomId); if (drawableTopId != -1) drawableTop = AppCompatResources.getDrawable(context, drawableTopId); } if(!attributeArray.hasValue(R.styleable.MyTextView_drawableWidthHeightCompatTextView)) { if (attributeArray.hasValue(R.styleable.MyTextView_drawableLeftCompatTextView)) { defaultWidthHeight = drawableLeft.getIntrinsicWidth(); } else if (attributeArray.hasValue(R.styleable.MyTextView_drawableStartCompatTextView)) { defaultWidthHeight = drawableStart.getIntrinsicWidth(); } else if (attributeArray.hasValue(R.styleable.MyTextView_drawableRightCompatTextView)) { defaultWidthHeight = drawableRight.getIntrinsicWidth(); } else if (attributeArray.hasValue(R.styleable.MyTextView_drawableEndCompatTextView)) { defaultWidthHeight = drawableEnd.getIntrinsicWidth(); } else if (attributeArray.hasValue(R.styleable.MyTextView_drawableBottomCompatTextView)) { defaultWidthHeight = drawableBottom.getIntrinsicWidth(); } else if (attributeArray.hasValue(R.styleable.MyTextView_drawableTopCompatTextView)) { defaultWidthHeight = drawableTop.getIntrinsicWidth(); } widthHeight = attributeArray.getInt(R.styleable.MyTextView_drawableWidthHeightCompatTextView, defaultWidthHeight); } else widthHeight = attributeArray.getInt(R.styleable.MyTextView_drawableWidthHeightCompatTextView, defaultWidthHeight); if(attributeArray.hasValue(R.styleable.MyTextView_drawableColorCompatTextView)){ ColorStateList tintColor = attributeArray.getColorStateList(R.styleable.MyTextView_drawableColorCompatTextView); if (attributeArray.hasValue(R.styleable.MyTextView_drawableLeftCompatTextView)) { //drawableLeft.setColorFilter(new PorterDuffColorFilter(tintColor.getDefaultColor(), PorterDuff.Mode.MULTIPLY)); DrawableCompat.setTintList(drawableLeft, tintColor); } else if (attributeArray.hasValue(R.styleable.MyTextView_drawableStartCompatTextView)) { //drawableStart.setColorFilter(new PorterDuffColorFilter(tintColor.getDefaultColor(), PorterDuff.Mode.MULTIPLY)); DrawableCompat.setTintList(drawableStart, tintColor); } else if (attributeArray.hasValue(R.styleable.MyTextView_drawableRightCompatTextView)) { //drawableRight.setColorFilter(new PorterDuffColorFilter(tintColor.getDefaultColor(), PorterDuff.Mode.MULTIPLY)); DrawableCompat.setTintList(drawableRight, tintColor); } else if (attributeArray.hasValue(R.styleable.MyTextView_drawableEndCompatTextView)) { //drawableEnd.setColorFilter(new PorterDuffColorFilter(tintColor.getDefaultColor(), PorterDuff.Mode.MULTIPLY)); DrawableCompat.setTintList(drawableEnd, tintColor); } else if (attributeArray.hasValue(R.styleable.MyTextView_drawableBottomCompatTextView)) { //drawableBottom.setColorFilter(new PorterDuffColorFilter(tintColor.getDefaultColor(), PorterDuff.Mode.MULTIPLY)); DrawableCompat.setTintList(drawableBottom, tintColor); } else if (attributeArray.hasValue(R.styleable.MyTextView_drawableTopCompatTextView)) { //drawableTop.setColorFilter(new PorterDuffColorFilter(tintColor.getDefaultColor(), PorterDuff.Mode.MULTIPLY)); DrawableCompat.setTintList(drawableTop, tintColor); } } WrappedDrawable drawableLeftWrapped = new WrappedDrawable(drawableLeft); drawableLeftWrapped.setBounds(0, 0, widthHeight, widthHeight); WrappedDrawable drawableStartWrapped = new WrappedDrawable(drawableStart); drawableStartWrapped.setBounds(0, 0, widthHeight, widthHeight); WrappedDrawable drawableRightWrapped = new WrappedDrawable(drawableRight); drawableRightWrapped.setBounds(0, 0, widthHeight, widthHeight); WrappedDrawable drawableEndWrapped = new WrappedDrawable(drawableEnd); drawableEndWrapped.setBounds(0, 0, widthHeight, widthHeight); WrappedDrawable drawableBottomWrapped = new WrappedDrawable(drawableBottom); drawableBottomWrapped.setBounds(0, 0, widthHeight, widthHeight); WrappedDrawable drawableTopWrapped = new WrappedDrawable(drawableTop); drawableTopWrapped.setBounds(0, 0, widthHeight, widthHeight); setCompoundDrawablesWithIntrinsicBounds(drawableLeftWrapped, drawableTopWrapped, drawableRightWrapped, drawableBottomWrapped); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) setCompoundDrawablesRelativeWithIntrinsicBounds(drawableStartWrapped, drawableTopWrapped, drawableEndWrapped, drawableBottomWrapped); attributeArray.recycle(); } } class WrappedDrawable extends Drawable { private final Drawable _drawable; protected Drawable getDrawable() { return _drawable; } public WrappedDrawable(Drawable drawable) { super(); _drawable = drawable; } @Override public void setBounds(int left, int top, int right, int bottom) { //update bounds to get correctly super.setBounds(left, top, right, bottom); Drawable drawable = getDrawable(); if (drawable != null) { drawable.setBounds(left, top, right, bottom); } } @Override public void setAlpha(int alpha) { Drawable drawable = getDrawable(); if (drawable != null) { drawable.setAlpha(alpha); } } @Override public void setColorFilter(ColorFilter colorFilter) { Drawable drawable = getDrawable(); if (drawable != null) { drawable.setColorFilter(colorFilter); } } @Override public int getOpacity() { Drawable drawable = getDrawable(); return drawable != null ? drawable.getOpacity() : PixelFormat.UNKNOWN; } @Override public void draw(Canvas canvas) { Drawable drawable = getDrawable(); if (drawable != null) { drawable.draw(canvas); } } @Override public int getIntrinsicWidth() { Drawable drawable = getDrawable(); return drawable != null ? drawable.getBounds().width() : 0; } @Override public int getIntrinsicHeight() { Drawable drawable = getDrawable(); return drawable != null ? drawable.getBounds().height() : 0; } } } 

attrs.xml:

 <declare-styleable name="MyTextView"> <attr name="drawableColorCompatTextView" format="reference|color"/> <attr name="drawableWidthHeightCompatTextView" format="integer"/> <attr name="drawableLeftCompatTextView" format="reference"/> <attr name="drawableStartCompatTextView" format="reference"/> <attr name="drawableRightCompatTextView" format="reference"/> <attr name="drawableEndCompatTextView" format="reference"/> <attr name="drawableTopCompatTextView" format="reference"/> <attr name="drawableBottomCompatTextView" format="reference"/> </declare-styleable> 

Using:

 <com.packagename.MyTextView android:id="@+id/txtUserName" android:layout_width="wrap_content" android:layout_height="wrap_content" app:drawableLeftCompatTextView="@drawable/ic_username" app:drawableStartCompatTextView="@drawable/ic_username" app:drawableWidthHeightCompatTextView="48" app:drawableColorCompatTextView="@color/blue" /> 

Note: The only problem here is an unmodified vector ( drawableWidthHeightCompatTextView not used), the width and height vector is 24, Not equal to the size on the device, with the modified vector (the width and height vector is 12 and drawableWidthHeightCompatTextView="24" ).

0
source

All Articles