为什么不是我的矢量绘制的缩放如预期?为什么不是我的矢量绘制的缩放如预期?(Why isn't

2019-05-13 07:21发布

我试图在我的Android应用程序使用矢量绘图资源。 从http://developer.android.com/training/material/drawables.html (重点煤矿):

在的Android 5.0(API等级21)及以上,则可以定义向量可绘, 其规模而不会失去清晰度。

使用这种绘制:

<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的移动设备上运行棒棒糖):

在载体中可绘制到显著200dp的定义改变的宽度和高度改善在400dp呈现大小的情况。 然而,设置此作为一个TextView元素(在文本的左边即图标)可拉伸现在造成了巨大的图标。

我的问题:

1)为什么会出现在向量可绘制的宽度/高度规范? 我想到这些整个的一点是,他们放大和缩小无损使宽度和高度的定义中毫无意义?

2)是否有可能使用单一的矢量绘制其作品作为一个TextView一个24dp绘制,但可扩展至以及过于使用尽可能多的较大的图像? 例如,如何避免创建多个不同尺寸的矢量绘图资源,而是使用其中一个扩展到我的渲染要求?

3)如何有效地使用宽度/高度属性是什么与viewportWidth /身高的区别?

额外细节:

  • 设备运行API 22
  • 使用过Android Studio V1.5.1与摇篮1.5.0版
  • 清单是编译和目标水平23分钟15级。我也试过分钟级移动到21,但是这并没有区别。
  • 反编译该APK(用分钟级别设置为21)示出了在绘制文件夹单个XML资源。 无光栅图像产生的。

Answer 1:

有关于这里这个问题的新信息:

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

它看起来像使用android:scaleType="fitXY"将使其正确缩放的棒棒糖。

从谷歌工程师:

嗨,让我知道如果scaleType =“fitXY”可以为你解决方法,以获取图像显得清晰。

Vs的棒棒糖棉花糖是由于加入棉花糖特殊的缩放处理。

此外,您的意见:“正确的行为:矢量绘制的规模应该没有质量损失因此,如果我们想用同样的资产在我们的应用3种不同的尺寸,我们不必重复vector_drawable.xml不同的3倍。硬编码的大小“。

尽管我完全同意这应该是这样的,在现实中,Android平台有性能问题,例如,我们还没有达到理想的世界呢。 因此,它实际上是建议使用更好的性能3种不同的vector_drawable.xml如果你确信你想在同一时间在屏幕上画出3种不同的大小。

技术细节基本上,我们使用的是钩下一个位图缓存复杂的路径渲染,这样我们就可以得到最佳的性能重新划分,在同水准与重绘位图绘制。



Answer 2:

1)为什么会出现在向量可绘制的宽度/高度规范? 我想到这些整个的一点是,他们放大和缩小无损使宽度和高度的定义中毫无意义?

对于SDK版本低于21,其中构建系统需要生成光栅图像,并在案件的默认大小,你不指定宽度/高度。

2)是否有可能使用单个载体可绘制其工作方式上一个TextView一个24dp可拉伸以及一个大的近屏幕宽度的图像?

我不相信这是可能的,如果你还需要为目标的SDK小于21。

3)如何有效地使用宽度/高度属性是什么与viewportWidth /身高的区别?

文件: (其实不是现在非常有用的,我重读了吧...)

android:width

用于定义绘制的固有宽度。 这种支持所有的尺寸单位,通常与DP规定。

android:height

用来定义真正高度的绘制。 这种支持所有的尺寸单位,通常与DP规定。

android:viewportWidth

用于定义视空间的宽度。 视口基本上是在路径被绘制在虚拟画布。

android:viewportHeight

用于定义视空间的高度。 视口基本上是在路径被绘制在虚拟画布。

更多的文档:

的Android 4.4(API级20)和较低的不支持向量可绘。 如果您的最低API级别设置这些API级别之一,矢量资源Studio还指导摇篮,生成反向兼容的矢量绘制的光栅图像。 你可以参考矢量资产Drawable在Java代码或@drawable在XML代码; 当你的应用程序运行时,相应的矢量或光栅图像自动显示根据API级别。


编辑:奇怪的事情是怎么回事。 这是我在模拟器SDK版本23的结果(棒棒堂+测试设备是死的,现在...):

而在模拟器SDK版本21:



Answer 3:

程序兼容性23.2引入载体可绘于运行Android 2.1及以上的所有设备。 图像缩放正确地,所述载体可绘制的XML文件中指定的宽度/高度的irregardless。 不幸的是,此实现不是API等级21以上的使用(有利于本机实现的)。

好消息是,我们可以强制程序兼容性使用其实施的API级别21和22。坏消息是,我们必须使用反射来做到这一点。

首先,确保你使用最新版本的程序兼容性,并已启用新的向量执行:

android {
  defaultConfig {
    vectorDrawables.useSupportLibrary = true
  }
}

dependencies {
    compile 'com.android.support:appcompat-v7:23.2.0'
}

然后,调用useCompatVectorIfNeeded(); 在您的应用程序的onCreate():

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

您可绘制矢量现在应该正确缩放!



Answer 4:

1)为什么会出现在向量可绘制的宽度/高度规范? 我想到这些整个的一点是,他们放大和缩小无损使宽度和高度的定义中毫无意义?

这是以防万一你没有在布局视图定义它的向量的默认大小。 (即您使用包装内容您的ImageView的高度和宽度)

2)是否有可能使用单个载体可绘制其工作方式上一个TextView一个24dp可拉伸以及一个大的近屏幕宽度的图像?

是的,这是可能的,我还没有为正在运行的设备正在使用棒棒糖或更高只要调整过任何问题。 在以前的API,当你构建应用程序的向量转换为PNG格式不同的屏幕大小。

3)如何有效地使用宽度/高度属性是什么与viewportWidth /身高的区别?

这会影响你周围的向量空间是如何被使用。 即你可以用它来改变视窗内向量的“万有引力”,使载体有一个默认的余量,留下载体的某些部位出了视区等......通常情况下,你只需将它们设置为相同的尺寸。



Answer 5:

我尝试这些方法必须的但不幸的是,他们没有工作。 我尝试fitXYImageView ,我尝试使用app:srcCompat但甚至不能使用它。 但我发现一个窍门方式:

设置可绘制到background您的ImageView

但这种方式的一点是查看维度。 如果您的ImageView尺寸不正确,绘制得到舒展。 你必须控制它棒棒糖之前的版本或使用一些看法PercentRelativeLayout

希望这是有帮助的。



Answer 6:

第一 :进口SVG到drawble:(( https://www.learn2crack.com/2016/02/android-studio-svg.html ))

在绘制文件夹1右键选择新建 - >矢量资源

2-矢量资源工作室为您提供选项来选择内置的材料图标或您自己的本地SVG文件。 如果需要,可以覆盖默认大小。

第二 :如果你想从Android的API支持7+,你必须使用Android的支持库acording(( https://stackoverflow.com/a/44713221/1140304 ))

1加

vectorDrawables.useSupportLibrary = true

您的build.gradle文件。

2,使用命名空间,你的布局,有ImageView的:

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

第三 :设置ImageView的与Android:scaleType = “fitXY”和使用应用程序: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);
    }


Answer 7:

我解决我的问题只是改变矢量图像的大小。 从第一个是资源,如:

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

它为我工作。



文章来源: Why isn't my vector drawable scaling as expected?