android:pivotY doesnt add top-padding to my android vector drawable - android

I have compactTextView with compoundDrawable.
I want to add top padding to that compoundDrawable which is fed by vector image (I imported svg into android studio)
I saw this post on how to add padding to a vector drawable
but when i try this, no padding is added:
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="13dp"
android:height="8dp"
android:autoMirrored="true"
android:viewportHeight="8.11"
android:viewportWidth="13.44">
<group
android:pivotX="0"
android:pivotY="12"
android:scaleX="1"
android:scaleY="1">
<path
android:fillColor="#FF000000"
android:pathData="M6.71,8.12l-6.71,-6.7l1.42,-1.42l5.29,5.3l5.29,-5.3l1.42,1.42z"/>
</group>
</vector>
do I need to add anything else?

The linked solution works by scaling down the path inside your VectorDrawable.
In the other example the viewPortWidth and viewportHeight were 24.
The pivotX and pivotY are the origin for the transform. It's equivalent to transform-origin in CSS. So thus setting the scaleX and scaleY to 0.5, results in their icon scaling down from 24x24 to 12x12, with the centre at the pivot point (12,12).
Thus you end up with a 12x12 icon in the middle of a 24x24 VectorDrawable. Thus creating a padding of 6 around the entire thing.
In your icon you have the scale attributes set to 1. So no scaling will happen, and you won't create any padding.
Are you sure you want to create padding space in your icon? The normal way to introduce padding is via your layout. For instance with android:layout_marginTop or android:paddingTop. I recommend you consider that approach first.
If you really do want to adjust your VectorDrawable. Then what you want to do to create padding only at the top, is to scale the shape down towards the bottom of the icon.
So have your pivot point at the bottom of the icon:
android:pivotX="0"
android:pivotY="8.11"
and scale down by an appropriate amount
android:scaleX="0.5"
android:scaleY="0.5"
Here we are scaling down toward the bottom left of the icon, so we are therefore also going to create padding on the right. Because we are also scaling in the X direction. You could counter that by reducing the width and viewportWidth.
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="7dp"
android:height="8dp"
android:autoMirrored="true"
android:viewportWidth="6.72"
android:viewportHeight="8.11">
<group
android:pivotX="0"
android:pivotY="8.11"
android:scaleX="0.5"
android:scaleY="0.5">
<path
android:fillColor="#FF000000"
android:pathData="M6.71,8.12l-6.71,-6.7l1.42,-1.42l5.29,5.3l5.29,-5.3l1.42,1.42z"/>
</group>
</vector>
You could also prevent the extra padding on the right by leaving scaleX at "1", but that will result in your icon having the appearance of being squashed vertically.
The translation approach
Another approach would be just to move the icon vertically downwards, to create space at the top, instead of scaling it in size. This has the advantage that you can more explicitly set the padding you want.
You do that by using the translateY attibute. Obviously that means that the height of the VectorDrawable has to change also. So you have to handle that by adjusting the viewportHeight.
In the example below, I have added a vertical padding of 4, mening the viewport height of the icon goes from 8.11 to 12.11.
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="13dp"
android:height="12dp"
android:autoMirrored="true"
android:viewportWidth="13.44"
android:viewportHeight="12.11">
<group
android:translateY="4">
<path
android:fillColor="#FF000000"
android:pathData="M6.71,8.12l-6.71,-6.7l1.42,-1.42l5.29,5.3l5.29,-5.3l1.42,1.42z"/>
</group>
</vector>
If you do this, you may also need to adjust the android:width and/or android:height.
You can choose to either:
increase the android:height as well to match the extra padding (ie to "12"), or
keep the height at 8, and adjust the width down to compensate (eg "9").

Related

Small SVG imageview looks blurry or "curvy"

I have generated a vector asset (based on an own svg file) via Android Studio.
The layout code of my image view:
<ImageView
android:id="#+id/iv_drink"
android:layout_width="21dp"
android:layout_height="30dp"
android:layout_marginStart="24dp"
android:layout_marginBottom="4dp"
android:scaleType="fitXY"
app:srcCompat="#drawable/ic_smoothie_icon" />
The issue is, that this small version of the image looks "curvy" or blurry. Below is a screenshot with increased size (so you can see the cury edges of the images).
My compileSdkVersion is 28 and minSdkVersion is 21.
I tried to solve this with the use of the following:
imageview: android:scaleType="fitXY"
imageview: app:srcCompat instead of app:src
build.gradle: vectorDrawables.useSupportLibrary = true
tried different sizes within the asset xml
What could cause this issue?
EDIT:
This is the content of the svg (image is based on a file from freepik.com):
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="-318 422.4 85.6 122.6" style="enable-background:new -318 422.4 85.6 122.6;" xml:space="preserve">
<g>
<path d="M-232.4,445l-6.1,100h-49.9l-6.1-100h20.7c-0.6-5.7-1-9.9-1.1-11.7c-0.3-4.8-1.6-6.1-2.1-6.5c-0.4-0.3-0.9-0.6-0.9-0.6
l-0.3-0.2H-318v-3.1c0,0,14.6-0.5,26.9-0.5c8.4,0,15.8,0.2,16.8,1c2.3,1.8,3.7,4.8,4,9.8c0.1,1.8,0.5,6.1,1.1,11.8L-232.4,445
L-232.4,445z"/>
</g>
</svg>
Vector xml:
<vector android:height="12.3dp" android:viewportHeight="123"
android:viewportWidth="86" android:width="8.6dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#000000" android:pathData="M85.6,22.6l-6.1,100h-49.9l-6.1,-100h20.7c-0.6,-5.7 -1,-9.9 -1.1,-11.7c-0.3,-4.8 -1.6,-6.1 -2.1,-6.5c-0.4,-0.3 -0.9,-0.6 -0.9,-0.6l-0.3,-0.2L0,3.6v-3.1c0,0 14.6,-0.5 26.9,-0.5c8.4,0 15.8,0.2 16.8,1c2.3,1.8 3.7,4.8 4,9.8c0.1,1.8 0.5,6.1 1.1,11.8L85.6,22.6L85.6,22.6z"/>
</vector>
Here i have made your vector using more scale friendly dimension and angles and remember that we can't draw half a pixel there will be anti-aliasing involved but we can mitigate by tweaking out shapes. when working with vector and animated vectors you can use shape-shifter to edit your path and make it android friendly or even animate it.
<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="M9,21L7,6L12,6C12,6,12.013,4.071,12,3.5C,11.987,2.929,12.081,3,11.5,3,L4,3L4,2C4,2,11.505,2.006,12,2,C12.26,2.015,12.506,2.125,12.691,2.309,C12.875,2.494,12.985,2.74,13,3L13,6L18,6L16,21Z"/>
</vector>
I think you're running up against the limits of how smooth a sloped line can look, at low resolution. The blurriness is due to anti-aliasing, which is an attempt to smooth out the jagged edge that would result from using only black or white pixels.
If you want to reduce the "curvy" effect, you can try changing the slope of the sides of the cup. Since your cup sides are almost vertical, there are a few large "steps" on each side, so the curviness is more noticeable. Make them completely vertical, or more slanted. A vertical line will have no steps. A more slanted line will have more steps, but smaller ones, so they should be less bumpy.
I think your problem is because of scaleType. Of course your vector width and height have problem too. Please try this:
<ImageView
android:id="#+id/iv_drink"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginBottom="4dp"
app:srcCompat="#drawable/ic_smoothie_icon" />
On my side moving to ConstraintLayout instead of using LinearLayout or FrameLayout removes the blurry quality on vector drawable.

Adaptive icon not displaying properly

I know that the foreground and background layers should both be 108dp by 108dp. But as you can see in the image its not displayed correctly (icon next to the YouTube icon)
I'm not sure what I'm doing wrong.
Here is the forground layer
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportHeight="512"
android:viewportWidth="512">
<path android:fillColor="#515262" android:pathData="M265.3,2.6c-5.7,-3.5 -12.8,-3.5 -18.6,0C202.7,29.5 17.7,150.6 17.7,289.7c0,72.3 58.5,130.9 130.7,130.9c23.6,0 45.8,-6.3 64.9,-17.3c5.5,-3.2 11.9,2.4 9.7,8.4c-10.2,28.4 -24.6,54.8 -42.6,78.2c-6.8,9 -0.3,22 10.9,22h130.7c11.2,0 17.8,-13 10.9,-22c-17.7,-23.2 -32,-49.2 -42.2,-77.3c-2.2,-6 4.2,-11.5 9.7,-8.5c18.7,10.4 40.3,16.4 63.2,16.4c72.2,0 130.7,-58.6 130.7,-130.9C494.3,150.6 309.3,29.5 265.3,2.6z"/>
<path android:fillColor="#464655" android:pathData="M202,409c-146.8,-81.3 -8.9,-325.2 55.3,-408.9c-3.6,-0.3 -7.3,0.5 -10.6,2.5C202.7,29.5 17.7,150.6 17.7,289.7c0,72.3 58.5,130.9 130.7,130.9C167.5,420.6 185.6,416.5 202,409z"/>
<path android:fillColor="#464655" android:pathData="M231.4,492.9c8.5,-70.3 8.1,-90.3 -13.5,-90.3c3.8,0.8 6.7,4.8 5.2,9.1c-10.2,28.4 -24.6,54.8 -42.6,78.2c-6.8,9 -0.3,22 10.9,22h49.4C230.9,512 230.5,499.9 231.4,492.9z"/>
</vector>
and the background layer which is a white square
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportHeight="108"
android:viewportWidth="108">
<path
android:fillColor="#FFF"
android:pathData="M0,0h108v108h-108z" />
</vector>
Per the Designing Adaptive Icons blog post:
Adaptive icons are 108dp*108dp in size but are masked to a maximum of 72dp*72dp. Different devices can supply different masks which must be convex in shape and may reach a minimum of 33dp from the center in places.
Because of the minimum reach of the mask, you can consider a centered 66dp diameter circle as a safe zone, guaranteed not to be clipped.
Your vector icon is using the entire 108x108dp size, rather than only the safe 66x66dp zone in the middle. Therefore what you are seeing is just the center of your icon (those two little white spots are actually the background peeking through).
You should resize your vector asset to fit into the safe zone. One way to do this is to increase the viewportHeight and viewportWidth, then put your paths into a <group> that uses android:translateX and android:translateY to recenter the vector in the larger viewport:
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportHeight="1024"
android:viewportWidth="1024">
<group
android:translateX="256"
android:translateY="256">
<path android:fillColor="#515262" android:pathData="M265.3,2.6c-5.7,-3.5 -12.8,-3.5 -18.6,0C202.7,29.5 17.7,150.6 17.7,289.7c0,72.3 58.5,130.9 130.7,130.9c23.6,0 45.8,-6.3 64.9,-17.3c5.5,-3.2 11.9,2.4 9.7,8.4c-10.2,28.4 -24.6,54.8 -42.6,78.2c-6.8,9 -0.3,22 10.9,22h130.7c11.2,0 17.8,-13 10.9,-22c-17.7,-23.2 -32,-49.2 -42.2,-77.3c-2.2,-6 4.2,-11.5 9.7,-8.5c18.7,10.4 40.3,16.4 63.2,16.4c72.2,0 130.7,-58.6 130.7,-130.9C494.3,150.6 309.3,29.5 265.3,2.6z"/>
<path android:fillColor="#464655" android:pathData="M202,409c-146.8,-81.3 -8.9,-325.2 55.3,-408.9c-3.6,-0.3 -7.3,0.5 -10.6,2.5C202.7,29.5 17.7,150.6 17.7,289.7c0,72.3 58.5,130.9 130.7,130.9C167.5,420.6 185.6,416.5 202,409z"/>
<path android:fillColor="#464655" android:pathData="M231.4,492.9c8.5,-70.3 8.1,-90.3 -13.5,-90.3c3.8,0.8 6.7,4.8 5.2,9.1c-10.2,28.4 -24.6,54.8 -42.6,78.2c-6.8,9 -0.3,22 10.9,22h49.4C230.9,512 230.5,499.9 231.4,492.9z"/>
</group>
</vector>
Or you can rewrite your paths manually.

android create drawable that is intersection between circle and rectangle

I would like to create an android xml drawable. That is the intersection between a circle and a rectangle.
Basically, i would like to have a rectangle. And then on the corner of this rectangle, draw a circle.
I would like to have the intersection of these two shapes to be used for a background.
This circle should have a radius slightly less than the height of the rectangle. So the intersection is not just 1/4 of the circle.
Is this something that can be created in a XML drawable in android?
Here is a very poorly drawn image using a trackpad..
The rectangle is what I would like to have for my background image. The shaded area should be able to have some color that I can change manually in the xml.
I would use a <vector> drawable here.
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="80dp"
android:viewportWidth="48"
android:viewportHeight="80">
<path
android:pathData="M48 0 a80 80 0 1 0 0.1 0z"
android:fillColor="#caf"/>
</vector>
You can then apply this to your layout using the android:background attribute:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/circle_rect_intersection"
...>
You can even tint it (to get different colors) using android:backgroundTint on your root view.

Right to left check arrow

I need right to left check arrow like the second arrow in picture for my background drawable in android
check arrow image
I need to rotate left to right check arrow vector icon
<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="#FFFFFFFF"
android:pathData="M9,16.2L4.8,12l-1.4,1.4L9,19 21,7l- 1.4,-1.4L9,16.2z"/>
</vector>
A simple way to flip an existing VectorDrawable like this is to scale it using a negative number.
The <group> tag of a VectorDrawable is where we can play with the scaleX and scaleY properties. Using these properties, a value of 1 is full size and a value of 0 is scaled down to nothing; 2 would be double the size, 0.5 would be half size etc.
If we use a negative number it shrinks all the way down to zero, then starts increasing in size in the opposite direction. So in your example, to flip the check-mark horizontally we can use:
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<group
android:pivotX="12"
android:scaleX="-1">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M9,16.2L4.8,12l-1.4,1.4L9,19 21,7l-1.4,-1.4L9,16.2z" />
</group>
</vector>
We wrapped the path in a <group> tag and gave it a scaleX value of -1, meaning the normal size but in the opposite direction. Also the pivotX value is 12, this is because the full width of your viewport is 24, and we want to flip the icon right around the centre line.
Which transforms this:
Into this:
Edit to add:
I see that your question is tagged with right-to-left, as in for languages which are read from right to left. The answer above may not be what you wanted in this case, so here's an alternative:
If you want the VectorDrawable to appear the original way when being used on a left-to-right device, but the opposite way on a right-to-left device then there is a specific property to enable this: autoMirrored.
By setting autoMirrored to true the drawable will show the default way in left-to-right mode but will be horizontally flipped when in right-to-left mode(but note this is only supported on API 19 and up):
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0"
android:autoMirrored="true">
<path
android:fillColor="#000000"
android:pathData="M9,16.2L4.8,12l-1.4,1.4L9,19 21,7l-1.4,-1.4L9,16.2z" />
</vector>

Android Vector Asset Studio gives extra padding to some vector images

I'm trying to import some icons from Material Vector package in Vector Asset Studio.
But they come with padding.
Why does this happen and how can I remove it?
This is inconvenient because this means if I want my icon to be 17dp x 17dp in XML, then I need to set it more than 17x17 to make up for the padding.
Android Vector Asset
You are able to scale a vector that will remove additional space. This is possible using group tag. Just modify your vector xml file.
From
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M12,4l-1.41,1.41L16.17,11H4v2h12.17l-5.58,5.59L12,20l8,-8z" />
</vector>
to
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<group
android:pivotX="12"
android:pivotY="12"
android:scaleX="1.5"
android:scaleY="1.5">
<path
android:fillColor="#FF000000"
android:pathData="M12,4l-1.41,1.41L16.17,11H4v2h12.17l-5.58,5.59L12,20l8,-8z" />
</group>
</vector>
As result
You can adjust for any "implicit" padding that may be contained within a VectorDrawables source image (.SVG, .PSD) by setting your ImageViews android:scaleType to the appropriate value so it can handle the padding that is secretly contained in the VectorDrawables source image. You will also need to set android:adjustViewBounds="true".
For example, lets say your VectorDrawable has some really annoying padding at the start of the image when you display it. You have no idea why it's there because you aren't setting any android:paddingStart on the ImageView... what you need to do is set the ImageViews android:scaleType to fitStart and android:adjustViewBounds to true.
tl;dr
Adjust your ImageViews android:scaleType to handle any "implicit" padding that is contained in your VectorDrawables source file (.SVG, .PSD). Also set android:adjustViewBounds="true".
Quick Example:
<ImageView android:id="#+id/vectorDrawable_imageView"
<!--Other ImageView settings-->
android:adjustViewBounds="true"
android:scaleType="fitStart"
app:srcCompat="#drawable/vector_with_implicit_padding_at_start"
/>
This will remove that annoying "implicit" padding that was at the start of your VectorDrawable.
Note: Adjust the android:scaleType according to your rendering needs.
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="28"
android:viewportHeight="28">
<group
android:translateX="2"
android:translateY="2">
<path
android:fillColor="#8A333333"
android:pathData="M13.12,2.06L7.58,7.6c-0.37,0.37 -0.58,0.88 -0.58,1.41V19c0,1.1 0.9,2 2,2h9c0.8,0 1.52,-0.48 1.84,-1.21l3.26,-7.61C23.94,10.2 22.49,8 20.34,8h-5.65l0.95,-4.58c0.1,-0.5 -0.05,-1.01 -0.41,-1.37 -0.59,-0.58 -1.53,-0.58 -2.11,0.01zM3,21c1.1,0 2,-0.9 2,-2v-8c0,-1.1 -0.9,-2 -2,-2s-2,0.9 -2,2v8c0,1.1 0.9,2 2,2z" />
</group>
</vector>
android:viewportWidth += android:translateX * 2 (padding start / end)
android:viewportHeight += android:translateY * 2 (padding top / bottom)
This padding is on some icons so that all of the icons can align properly. For example, if in that dialog, you pick ic_3d_rotation_24dp, you'll see the icon goes all the way to the edge of the bounds.
PS if you aim to have all your sizes be a multiple of 8dp, things will line up nicely and look great.

Categories

Resources