Why is my vector scalable scaling not expected?

I am trying to use vector drawings in my android application. From http://developer.android.com/training/material/drawables.html (my highlight):

In Android 5.0 (API Level 21) and higher, you can define vector drawings , which scale without loss of definition.

Using this feature:

<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:width="24dp" android:viewportWidth="24" android:viewportHeight="24"> <path android:fillColor="@color/colorPrimary" android:pathData="M14,20A2,2 0 0,1 12,22A2,2 0 0,1 10,20H14M12,2A1,1 0 0,1 13,3V4.08C15.84,4.56 18,7.03 18,10V16L21,19H3L6,16V10C6,7.03 8.16,4.56 11,4.08V3A1,1 0 0,1 12,2Z" /> 

and this ImageView:

 <ImageView android:layout_width="400dp" android:layout_height="400dp" android:src="@drawable/icon_bell"/> 

creates this blurry image when trying to display the icon on 400dp (on a fairly large low-resolution mobile device around 2015 using a lollipop):

blurryIcon

Changing the width and height in the definition of a vector suitable for 200dp significantly improves the situation at a size of 400dp. However, setting this parameter as an element for text (for example, to the left of the text) now creates a huge icon.

My questions:

1) Why is the width / height specification in the vector available? I thought the whole thing is that they scale up and down without loss, making width and height meaningless in their definition?

2) Is it possible to use a single vector drawing that works like 24dp, extruded in a TextView, but scales well to use also large images? For example. How can I avoid creating multiple vector drawings of different sizes and use the one that scales to my visualized requirements instead?

3) How to use width / height attributes effectively and what is the difference with viewportWidth / Height?

Additional Information:

  • The device works with API 22
  • Using Android Studio v1.5.1 with Gradle version 1.5.0
  • The manifest is compilation and the target level is 23, the minimum level is 15. I also tried to move the minimum level to 21, but that didn't matter.
  • Decompiling the APK (with a minimum level set to 21) shows one XML resource in a portable folder. Rasterized images are not created.
+84
android vector drawable scaling
Jan 21 '16 at 23:48
source share
8 answers

Here is new information about this issue:

https://code.google.com/p/android/issues/detail?id=202019

It looks like android:scaleType="fitXY" will do the proper scaling on Lollipop.

From a Google engineer:

Hi, let me know if scaleType = 'fitXY' might be a workaround for you to make the image look sharp.

Marshmallow Vs Lollipop is due to a special scaling treatment added to the marshmallow.

In addition, for your comments: “The correct behavior: the vector vector must scale without quality loss. Therefore, if we want to use the same asset in 3 different sizes in our application, we do not need to duplicate vector_drawable.xml 3 times with different hard given dimensions. "

Despite the fact that I completely agree that this should be so, in fact, the Android platform has performance problems, so we have not reached a perfect world. Therefore, it is actually recommended to use 3 different vector_drawable.xml for better performance if you are sure that you want to draw 3 different sizes on the screen at the same time.

The technical information mainly consists in using a bitmap under the hook to cache a complex path so that we can get the best performance redrawing results, along with redrawing a bitmap.

+93
Mar 11 '16 at 1:15
source share

1) Why is the width / height specification in the vector available? I thought the whole thing is that they scale up and down without loss, making width and height meaningless in their definition?

For SDK versions less than 21, where the build system needs to generate bitmaps and as the default size in cases where you do not specify the width / height.

2) Is it possible to use a single vector drawing that works like 24dp, extruded to a TextView, as well as an image with a wide screen width?

I don’t think it’s possible if you also need to target less than 21 SDKs.

3) How to use width / height attributes effectively and what is the difference with viewportWidth / Height?

Documentation: (actually not very useful now when I re-read it ...)

android:width

Used to determine the internal width of the extruded. This supports all units usually specified with dp.

android:height

Used to determine the internal height. This supports all units usually specified with dp.

android:viewportWidth

Used to determine the width of the viewing space. Viewport is basically a virtual canvas on which paths are drawn.

android:viewportHeight

Used to determine the height of the viewing space. Viewport is basically a virtual canvas on which paths are drawn.

Additional documentation:

Android 4.4 (API level 20) and below does not support vector drawings. If your minimum API level is set to one of these API levels, Vector Asset Studio also directs Gradle to generate backward compatible vector raster images. You can refer to vector assets as Drawable in Java code or @drawable in XML code; when the application starts, the corresponding vector or bitmap image is automatically displayed depending on the level of the API.




Edit: Something strange is happening. Here are my results in SDK emulator version 23 (test device Lollipop + is already dead ...):

Good bells on 6.x

And in the SDK emulator version 21:

Crappy bells on 5.x

+25
Jan 21 '16 at 23:56 on
source share

AppCompat 23.2 presents vector drawings for all devices running Android 2.1 and higher. Images scale correctly, regardless of the width / height specified in the XML vector file. Unfortunately, this implementation is not used in API level 21 and higher (in favor of its own implementation).

The good news is that we can get AppCompat to use its implementation at API levels 21 and 22. The bad news is that we need to use reflection for this.

First of all, make sure that you are using the latest version of AppCompat and that you have included a new implementation of the vector:

 android { defaultConfig { vectorDrawables.useSupportLibrary = true } } dependencies { compile 'com.android.support:appcompat-v7:23.2.0' } 

Then call useCompatVectorIfNeeded(); in your onCreate () application:

 private void useCompatVectorIfNeeded() { int sdkInt = Build.VERSION.SDK_INT; if (sdkInt == 21 || sdkInt == 22) { //vector drawables scale correctly in API level 23 try { AppCompatDrawableManager drawableManager = AppCompatDrawableManager.get(); Class<?> inflateDelegateClass = Class.forName("android.support.v7.widget.AppCompatDrawableManager$InflateDelegate"); Class<?> vdcInflateDelegateClass = Class.forName("android.support.v7.widget.AppCompatDrawableManager$VdcInflateDelegate"); Constructor<?> constructor = vdcInflateDelegateClass.getDeclaredConstructor(); constructor.setAccessible(true); Object vdcInflateDelegate = constructor.newInstance(); Class<?> args[] = {String.class, inflateDelegateClass}; Method addDelegate = AppCompatDrawableManager.class.getDeclaredMethod("addDelegate", args); addDelegate.setAccessible(true); addDelegate.invoke(drawableManager, "vector", vdcInflateDelegate); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } } 

Finally, make sure you use app:srcCompat instead of android:src to install the ImageView image:

 <ImageView android:layout_width="400dp" android:layout_height="400dp" app:srcCompat="@drawable/icon_bell"/> 

Now your vector drawings will scale correctly!

+9
Mar 05 '16 at 16:44
source share

1) Why is the width / height specification in the vector available? I thought the whole thing is that they scale up and down without loss, making width and height meaningless in their definition?

This is only the default size for a vector if you do not define it in the layout. (i.e. you use the contents of the package for the height and width of your image)

2) Is it possible to use a single vector drawing that works like 24dp, extruded to a TextView, as well as an image with a wide screen width?

Yes, it is possible, and I did not have problems with resizing since the working device uses candy or higher. In the previous API, the vector is converted to png for different screen sizes when you create the application.

3) How to use width / height attributes effectively and what is the difference with viewportWidth / Height?

This affects the use of the space around your vector. those. you can use it to change the "gravity" of the vector inside the viewport, make the vector have a default value, leave certain parts of the vector from the viewport, etc. Usually you just set them the same size.

+6
Jan 22 '16 at 0:11
source share

I try this, but unfortunately none of them worked. I am trying to fitXY in ImageView , I am trying to use app:srcCompat , but I can't even use it. but I found a trick:

set the background value of your ImageView .

But the point of this path is the view sizes. if your ImageView is the wrong size, drawable gets a Stretch. You must control it in pre-Lellipop versions or use some kind of PercentRelativeLayout .

Hope this will be helpful.

+3
Mar 14 '16 at 22:35
source share

First : import svg to drawble: (( https://www.learn2crack.com/2016/02/android-studio-svg.html ))

1-Right-click on the selected folder, select "Create" → "Vector object"

enter image description here

2. Vector Asset Studio gives you the opportunity to choose the built-in Material Icons or your own local svg file. You can override the default size if necessary.

enter image description here

Second one . If you need support from android API 7+, you should use the support of the Android support library (( https://stackoverflow.com/a/167378/ ))

1- add

 vectorDrawables.useSupportLibrary = true 

to the build.gradle file.

2-Use the namespace in your image layout:

 xmlns:app="http://schemas.android.com/apk/res-auto" 

Third : set the image using android: scaleType = "fitXY" and use the application: srcCompat

  <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="fitXY" app:srcCompat="@drawable/ic_menu" /> 

Fourth : if you want to install svg in java code, you need to add the line below oncreate methoed

  @Override protected void onCreate(Bundle savedInstanceState) { AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } 
+2
Oct 10 '17 at 11:04 on
source share

I solve my problem by simply resizing the vector image. From the very beginning, it was a resource like:

 <vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt" android:width="24dp" android:height="24dp" android:viewportHeight="300" android:viewportWidth="300"> 

And I changed it to 150dp (ImageView size in layout with this vector resource), for example:

 <vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt" android:width="150dp" android:height="150dp" android:viewportHeight="300" android:viewportWidth="300"> 

This works for me.

+1
Aug 13 '18 at 10:07
source share

For me, the reason the vectors were converted to png was the android:fillType="evenodd" in my vector object. When I deleted all occurrences of this attribute in my drawable (that is, in a vector using the default fill type nonzero ), the next time the application was built, everything was fine.

+1
Jul 28 '19 at 11:46
source share



All Articles