我正在尝试在我的Android应用中使用矢量绘图。来自http://developer.android.com/training/material/drawables.html(强调我的):
在Android 5.0(API Level 21)及更高版本中,您可以定义矢量绘图,在不丢失定义的情况下进行缩放。
使用这个drawable:
<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" />
和这个ImageView:
<ImageView
android:layout_width="400dp"
android:layout_height="400dp"
android:src="@drawable/icon_bell"/>
尝试以400dp显示图标时,会产生这种模糊的图像(在2015年左右的大型高分辨率移动设备上运行棒棒糖):
将矢量drawable的定义中的宽度和高度更改为200dp可显着改善400dp渲染大小的情况。但是,将其设置为TextView元素的drawable(即文本左侧的图标)现在会创建一个巨大的图标。
我的问题:
1)为什么矢量可绘制中有宽度/高度规格?我认为这些的全部意义在于它们无损扩大和缩小,使得宽度和高度在其定义中毫无意义?
2)是否可以使用单个矢量drawable,它可以在TextView上作为24dp绘图,但可以很好地扩展以使用更大的图像?例如。如何避免创建不同大小的多个矢量绘图,而是使用一个可以扩展到渲染需求的矢量绘图?
3)如何有效地使用width / height属性以及viewportWidth / Height的区别是什么?
其他详情:
答案 0 :(得分:88)
此处有关于此问题的新信息:
https://code.google.com/p/android/issues/detail?id=202019
看起来像是在使用
android:scaleType="fitXY"
会让它在Lollipop上正确缩放。
来自Google工程师:
嗨,请告诉我scaleType =&#39; fitXY&#39;可以为你提供一种解决方法 为了让图像看起来更清晰。
棉花糖Vs棒棒糖是由于特殊的结垢处理 添加到棉花糖中。
另外,对于你的意见:&#34;正确的行为:矢量drawable 应该在没有质量损失的情因此,如果我们想要使用相同的资产 在我们的应用程序中有3种不同的尺寸,我们不必复制 vector_drawable.xml使用不同的硬编码大小3次。 &#34;
即使我完全同意这应该是这样的,实际上, Android平台存在性能问题,我们还没有达到 理想的世界。所以实际上建议使用3种不同的 如果您确定需要,可以使用vector_drawable.xml获得更好的性能 在屏幕上同时绘制3种不同的尺寸。
技术细节基本上我们在钩子下使用位图 缓存复杂的路径渲染,这样我们就可以获得最佳效果 重绘性能,与重绘位图drawable相同。
答案 1 :(得分:25)
1)为什么矢量可绘制中有宽度/高度规格?我认为这些的全部意义在于它们无损扩大和缩小,使得宽度和高度在其定义中毫无意义?
对于小于21的SDK版本,构建系统需要生成光栅图像,并且在不指定宽度/高度的情况下作为默认大小。
2)是否可以使用单个矢量drawable,它在TextView上作为24dp可绘制,以及大的近屏宽度图像?
如果您还需要定位低于21的SDK,我也不相信这是可能的。
3)如何有效地使用width / height属性以及viewportWidth / Height的区别是什么?
Documentation:(现在我重读了它真的不太有用......)
android:width
用于定义drawable的固有宽度。这支持所有维度单位,通常用dp。
指定
android:height
用于定义drawable的内在高度。这支持所有维度单位,通常用dp。
指定
android:viewportWidth
用于定义视口空间的宽度。视口基本上是绘制路径的虚拟画布。
android:viewportHeight
用于定义视口空间的高度。视口基本上是绘制路径的虚拟画布。
Android 4.4(API级别20)及更低版本不支持矢量绘图。如果您的最低API级别设置为其中一个API级别,Vector Asset Studio还会指示Gradle生成向量drawable的光栅图像以实现向后兼容性。您可以在Java代码中将矢量资产称为
Drawable
,或在XML代码中将@drawable
称为矢量资产;当您的应用运行时,相应的矢量或光栅图像会根据API级别自动显示。
编辑:正在发生一些奇怪的事情。这是我在模拟器SDK版本23中的结果(Lollipop +测试设备现在已经死了......):
在模拟器SDK版本21中:
答案 2 :(得分:9)
AppCompat 23.2为所有运行Android 2.1及更高版本的设备引入了矢量绘图。无论vector drawable的XML文件中指定的宽度/高度如何,图像都能正确缩放。遗憾的是,此实现未在API级别21及更高版本中使用(支持本机实现)。
好消息是我们可以强制AppCompat在API级别21和22上使用它的实现。 坏消息是我们必须使用反射来做到这一点。
首先,确保您使用的是最新版本的AppCompat,并且已启用新的矢量实现:
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
dependencies {
compile 'com.android.support:appcompat-v7:23.2.0'
}
然后,在应用程序的onCreate()中调用useCompatVectorIfNeeded();
:
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();
}
}
}
最后,请确保您使用app:srcCompat
代替android:src
来设置ImageView的图像:
<ImageView
android:layout_width="400dp"
android:layout_height="400dp"
app:srcCompat="@drawable/icon_bell"/>
您的矢量绘图现在应该正确缩放!
答案 3 :(得分:6)
1)为什么矢量可绘制中有宽度/高度规格?我认为这些的全部意义在于它们无损扩大和缩小,使得宽度和高度在其定义中毫无意义?
如果您没有在布局视图中定义它,那么这只是矢量的默认大小。 (即你使用包裹内容的高度和 你的imageview的宽度)
2)是否可以使用单个矢量drawable,它在TextView上作为24dp可绘制,以及大的近屏宽度图像?
是的,有可能,我没有任何调整大小的问题 只要正在运行的设备使用棒棒糖或更高。在以前 API,当矢量转换为不同屏幕尺寸的png 你构建应用程序。
3)如何有效地使用width / height属性以及viewportWidth / Height的区别是什么?
这会影响矢量周围空间的使用方式。即你可以 用它来改变视口内矢量的“重力”,make 向量具有默认边距,保留向量的某些部分 超出视口等...通常,你只需将它们设置为相同 大小
答案 4 :(得分:3)
我必须尝试这些方法但不幸的是,它们都没有奏效。
我在fitXY
中尝试ImageView
,我尝试使用app:srcCompat
,但甚至无法使用它。
但我发现了一种技巧:
将Drawable设置为
background
的{{1}}。
但这种方式的重点是视图维度。如果您的ImageView
尺寸不正确,则drawable会获得Stretch。您必须在pre-lollipop版本中控制它或使用一些视图ImageView
。
希望它有所帮助。
答案 5 :(得分:2)
首先:将svg导入drawble:((https://www.learn2crack.com/2016/02/android-studio-svg.html))
1 - 右键单击drawable文件夹,选择New - &gt;矢量资产
2- Vector Asset Studio提供了选择内置的选项 材质图标或您自己的本地svg文件。你可以覆盖 默认大小,如果需要。
第二次:如果您需要Android API 7+的支持,则必须使用Android支持库编写(https://stackoverflow.com/a/44713221/1140304))
1-添加
vectorDrawables.useSupportLibrary = true
到你的build.gradle文件。
2 - 在布局中使用包含imageView:
的命名空间xmlns:app="http://schemas.android.com/apk/res-auto"
第三次:使用android设置imageView:scaleType =“fitXY”并使用app:srcCompat
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY"
app:srcCompat="@drawable/ic_menu" />
第四:如果你想在java代码中设置svg,你必须在oncreate methoed上添加以下行
@Override
protected void onCreate(Bundle savedInstanceState)
{
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
答案 6 :(得分:1)
我解决了我的问题,只需更改矢量图像的大小即可。从一开始它就是这样的资源:
<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">
我将其更改为150dp(具有此矢量资源的布局中ImageView的大小),例如:
<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">
对我有用。
答案 7 :(得分:0)
对我来说,导致矢量转换为png的原因是我的矢量可绘制对象中的 android:fillType="..."
属性。当我删除我的可绘制对象中所有出现的该属性时,下次编译该应用程序时一切正常。