矢量图渲染问题

18

我在使用支持库引入的VectorDrawables时遇到了问题。

我查找了一些资料,发现有关Android Studio中错误缩放或预览不正确的类似问题。但是,我的问题很不幸与此不同。

问题:

实际上,我的VectorDrawable在Android Studio预览中渲染完美,但在设备上运行时变得混乱(Android v.5.1.1和6.0)。

导出:

从一个SVG文件(只有一个复合路径)开始,我使用Android Studio工具将其导入(但我也尝试了许多其他工具进行转换)。 该文件的制作方式与一堆其他文件相同,但只有一些会渲染失败。

我已经尝试过的方法:

我尝试使用app:srcCompat(甚至使用src:)将其设置在imageView中。 我尝试在菜单中使用它(直接设置图标或使用selector)。

SVG代码:

<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 626.96 610.53"><title>PATHOLOGIES</title><path d="M5766.55,588.54a54.73,54.73,0,0,0-4.23-3.81,248.33,248.33,0,0,0,31.34-121.54c-0.23-138.68-114.72-251.15-253.38-249-134.71,2.07-243.52,110.91-245.54,245.64a249.48,249.48,0,0,0,390.59,209.52l0.21,0.22,155.12,155.12,81-81Zm-222.36,64.92c-104.85,0-189.85-85-189.85-189.85s85-189.85,189.85-189.85S5734,358.76,5734,463.61,5649,653.46,5544.19,653.46ZM5452,347.1l7.72-22.08a161.29,161.29,0,0,1,52.5-20.55l-19.84,56.75A19.25,19.25,0,0,1,5467.83,373l-4-1.41A19.25,19.25,0,0,1,5452,347.1Zm20.13,82.62L5430,502.57a19.25,19.25,0,0,1-26.29,7l-3.71-2.14a19.25,19.25,0,0,1-7-26.29L5435,408.33a19.25,19.25,0,0,1,26.29-7l3.71,2.14A19.25,19.25,0,0,1,5472.1,429.72Zm-82.73-14.9A161.59,161.59,0,0,1,5408.85,374l9.06,9.06a19.25,19.25,0,0,1,0,27.22l-3,3A19.24,19.24,0,0,1,5389.37,414.82Zm151.76-54A19.25,19.25,0,0,1,5552,335.85l55.51-21.72a162.36,162.36,0,0,1,43.87,27.64A19.17,19.17,0,0,1,5646,345l-78.34,30.65a19.25,19.25,0,0,1-24.94-10.91Zm-13.43,29.12,66.74,51.21a19.25,19.25,0,0,1,3.55,27l-2.61,3.4a19.25,19.25,0,0,1-27,3.55l-66.74-51.21a19.25,19.25,0,0,1-3.55-27l2.61-3.4A19.25,19.25,0,0,1,5527.69,389.91Zm83.57,191.47-2.82,3.23a19.25,19.25,0,0,1-27.15,1.86l-63.41-55.28A19.25,19.25,0,0,1,5516,504l2.82-3.23a19.25,19.25,0,0,1,27.16-1.86l63.41,55.28A19.25,19.25,0,0,1,5611.26,581.38Zm60.09-191.15,4,1.59a19.25,19.25,0,0,1,10.71,25l-31.28,78.09a19.25,19.25,0,0,1-25,10.71l-4-1.59A19.25,19.25,0,0,1,5615,479l31.28-78.09A19.25,19.25,0,0,1,5671.34,390.24ZM5504.73,604.39a19.19,19.19,0,0,1-4.85,15.4,161.36,161.36,0,0,1-38.43-16.53l-9.92-76.83a19.25,19.25,0,0,1,16.62-21.55l4.25-.55A19.25,19.25,0,0,1,5494,521ZM5686.4,538L5685,544.4a163.11,163.11,0,0,1-56.5,57.93l16.12-73.51a19.25,19.25,0,0,1,22.92-14.68l4.19,0.92A19.25,19.25,0,0,1,5686.4,538Z" transform="translate(-5294.72 -214.14)"/></svg>

矢量图形代码:

<vector android:height="24dp" android:viewportHeight="610.53"
android:viewportWidth="626.96" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M471.8,374.4a54.7,54.7 0,0 0,-4.2 -3.8,248.3 248.3,0 0,0 31.3,
-121.5c-0.2,-138.7 -114.7,-251.1 -253.4,-249 -134.7,2.1 -243.5,110.9 -245.5,245.6a249.5,249.5 0,0 0,390.6 209.5l0.2,
0.2 155.1,155.1 81,-81ZM249.5,439.3c-104.8,0 -189.9,-85 -189.9,-189.9s85,-189.9 189.9,-189.9S439.3,144.6 439.3,
249.5 354.3,439.3 249.5,439.3ZM157.3,133l7.7,-22.1a161.3,161.3 0,0 1,52.5 -20.5l-19.8,56.8A19.3,19.3 0,0 1,
173.1 158.9l-4,-1.4A19.3,19.3 0,0 1,157.3 133ZM177.4,215.6L135.3,288.4a19.3,19.3 0,0 1,-26.3 7l-3.7,-2.1a19.3,
19.3 0,0 1,-7 -26.3L140.3,194.2a19.3,19.3 0,0 1,26.3 -7l3.7,2.1A19.3,19.3 0,0 1,177.4 215.6ZM94.7,200.7A161.6,
161.6 0,0 1,114.1 159.9l9.1,9.1a19.3,19.3 0,0 1,0 27.2l-3,3A19.2,19.2 0,0 1,94.6 200.7ZM246.4,146.7A19.3,19.3 0,
0 1,257.3 121.7l55.5,-21.7a162.4,162.4 0,0 1,43.9 27.6A19.2,19.2 0,0 1,351.3 130.9l-78.3,30.6a19.3,19.3 0,0 1,
-24.9 -10.9ZM233,175.8 L299.7,227a19.3,19.3 0,0 1,3.5 27l-2.6,3.4a19.3,19.3 0,0 1,-27 3.5l-66.7,-51.2a19.3,19.3 0,
0 1,-3.5 -27l2.6,-3.4A19.3,19.3 0,0 1,233 175.8ZM316.6,367.3 L313.8,370.5a19.3,19.3 0,0 1,-27.1 1.9l-63.4,-55.3A19.3,
19.3 0,0 1,221.3 289.9l2.8,-3.2a19.3,19.3 0,0 1,27.2 -1.9l63.4,55.3A19.3,19.3 0,0 1,316.5 367.2ZM376.7,176.1 L380.7,
177.7a19.3,19.3 0,0 1,10.7 25l-31.3,78.1a19.3,19.3 0,0 1,-25 10.7l-4,-1.6A19.3,19.3 0,0 1,320.3 264.9l31.3,-78.1A19.3,
19.3 0,0 1,376.6 176.1ZM210,390.3a19.2,19.2 0,0 1,-4.8 15.4,161.4 161.4,0 0,1 -38.4,-16.5l-9.9,-76.8a19.3,19.3 0,0 1,
16.6 -21.5l4.3,-0.6A19.3,19.3 0,0 1,199.3 306.9ZM391.7,323.9L390.3,330.3a163.1,163.1 0,0 1,-56.5 57.9l16.1,-73.5a19.3,
19.3 0,0 1,22.9 -14.7l4.2,0.9A19.3,19.3 0,0 1,391.7 323.9Z"/>

在Android Studio中呈现的样子:

As rendered on Android Studio

在设备上呈现的样子(在导入AndroidStudio后):

As rendered on device

我真的无法弄清楚是什么导致了糟糕的渲染。 我非常确定这不是一个SVG问题(如果我错了,请纠正我),因为其他可绘制部分渲染正确。 甚至我也不会称之为库错误,因为我碰巧是唯一遇到此问题的人。 我做错了什么?

感谢帮助


这看起来像是与以下问题相同:https://dev59.com/cloT5IYBdhLWcg3wxxwl - steakunderscore
4个回答

9
在我的情况下,除非将所有椭圆弧命令(A)替换为三次贝塞尔曲线命令(C),否则没有任何帮助。任何弧线都可以用一个或几个贝塞尔曲线来表示。整个椭圆可以用四条贝塞尔曲线替代。
Inkscape倾向于在SVG中编辑路径后将弧线转换为贝塞尔曲线,因此您可以使用Inkscape进行转换。看起来Android矢量渲染器在处理A/a命令时存在严重问题,无论它们是相对的还是绝对的。因此,尝试将A/a => C/c进行转换。
请注意,仅更改命令字母是不够的,您需要适当设置控制点。

2
你救了我的一天,谢谢。我所需要做的就是:将SVG加载到Inkscape中,选择曲线上的一个点,然后向左移动一步,再向右移动一步(回到相同的位置)。保存并导入后,它也可以在旧的操作系统版本上运行。(“A / a”命令变成了“C / c”。) - racs

8

原生控件无法显示弧形,但是appCompat可以。因此,改为:

<ImageView
    android:src="@drawable/mydrawable"
/>

使用

app:srcCompat="@drawable/mydrawable"

很简单 o_O。(appxmlns:app="http://schemas.android.com/apk/res-auto"

我不知道现在是否有效,但在发布此帖子时,srcCompat在渲染方面存在问题(正如问题中所述)。因此,如果仍然存在这种问题,我想我的答案和其他答案仍然可能有用。 - Francesco Ambrosini
@FrancescoAmbrosini,我现在发布它是因为它现在可以工作了。截至2018年,这是最佳解决方案,因为它既不涉及修改图像也不涉及修改显示方式。其他答案提供了很好的历史背景,但现在已经过时了。 - Agent_L

4

解决方案

通过多次尝试(和他人的帮助),我找到了问题所在。 问题出在fill-rule上,与其他人遇到的问题恰恰相反!

事实上,据我所知,VectorDrawable使用的是non-zero fill-rule,并且与使用evenodd规则导出的SVG存在渲染问题。这就是为什么我一直使用non-zero规则。结果发现使用android:fillType="evenOdd"可以解决我的问题。

我不知道为什么,此时我也太害怕问了。


这个工具应该可以解决你的问题:http://a-student.github.io/SvgToVectorDrawableConverter.Web/ - A-student
1
从你的截图来看,我不认为这是填充问题,因为它看起来像路径中的某些部分(点)被忽略了。我认为保罗是正确的。 - AaA

2

我怀疑这与路径命令解析有关。如果我们看一下您的路径的第一个子路径(未正确绘制的子路径),它看起来像以下内容:

M 471.8, 374.4
a 54.7, 54.7 0, 0 0, -4.2 -3.8,
  248.3 248.3, 0 0, 0 31.3,-121.5
c -0.2, -138.7 -114.7, -251.1 -253.4, -249
  -134.7, 2.1 -243.5, 110.9 -245.5, 245.6
a 249.5, 249.5 0, 0 0, 390.6 209.5
l 0.2, 0.2
  155.1, 155.1
  81, -81Z

我已经将其分解以便阅读。

您可以看到它正在使用SVG路径命令字符串的一个特性,即如果重复使用路径命令,则可以跳过它并只提供坐标。它在这里用于a(弧形)、c(曲线)和l(线条)命令。

虽然线段(形成手柄)似乎渲染正常,但我怀疑VectorDrawable渲染器没有正确解析弧形和/或曲线段。但是,我还没有查看Android代码库以确认错误。

我建议您尝试将跳过的路径命令字符放回路径中,以查看是否效果更好。例如:

M 471.8, 374.4
a 54.7, 54.7 0, 0 0, -4.2 -3.8
a 248.3 248.3, 0 0, 0 31.3,-121.5
c -0.2, -138.7 -114.7, -251.1 -253.4, -249
c -134.7, 2.1 -243.5, 110.9 -245.5, 245.6
a 249.5, 249.5 0, 0 0, 390.6 209.5
l 0.2, 0.2
  155.1, 155.1
  81, -81Z

字符串中稍后还有另一个子路径(对应于其中一个“药片”),也使用了重复的坐标快捷方式。如果我们也修改它,生成的VectorDrawable如下:

<vector android:height="24dp" android:viewportHeight="610.53"
android:viewportWidth="626.96" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M471.8,374.4a54.7,54.7 0,0 0,-4.2 -3.8a248.3 248.3,0 0,0 31.3,
-121.5c-0.2,-138.7 -114.7,-251.1 -253.4,-249c-134.7,2.1 -243.5,110.9 -245.5,245.6a249.5,249.5 0,0 0,390.6 209.5l0.2,
0.2 155.1,155.1 81,-81ZM249.5,439.3c-104.8,0 -189.9,-85 -189.9,-189.9s85,-189.9 189.9,-189.9S439.3,144.6 439.3,
249.5 354.3,439.3 249.5,439.3ZM157.3,133l7.7,-22.1a161.3,161.3 0,0 1,52.5 -20.5l-19.8,56.8A19.3,19.3 0,0 1,
173.1 158.9l-4,-1.4A19.3,19.3 0,0 1,157.3 133ZM177.4,215.6L135.3,288.4a19.3,19.3 0,0 1,-26.3 7l-3.7,-2.1a19.3,
19.3 0,0 1,-7 -26.3L140.3,194.2a19.3,19.3 0,0 1,26.3 -7l3.7,2.1A19.3,19.3 0,0 1,177.4 215.6ZM94.7,200.7A161.6,
161.6 0,0 1,114.1 159.9l9.1,9.1a19.3,19.3 0,0 1,0 27.2l-3,3A19.2,19.2 0,0 1,94.6 200.7ZM246.4,146.7A19.3,19.3 0,
0 1,257.3 121.7l55.5,-21.7a162.4,162.4 0,0 1,43.9 27.6A19.2,19.2 0,0 1,351.3 130.9l-78.3,30.6a19.3,19.3 0,0 1,
-24.9 -10.9ZM233,175.8 L299.7,227a19.3,19.3 0,0 1,3.5 27l-2.6,3.4a19.3,19.3 0,0 1,-27 3.5l-66.7,-51.2a19.3,19.3 0,
0 1,-3.5 -27l2.6,-3.4A19.3,19.3 0,0 1,233 175.8ZM316.6,367.3 L313.8,370.5a19.3,19.3 0,0 1,-27.1 1.9l-63.4,-55.3A19.3,
19.3 0,0 1,221.3 289.9l2.8,-3.2a19.3,19.3 0,0 1,27.2 -1.9l63.4,55.3A19.3,19.3 0,0 1,316.5 367.2ZM376.7,176.1 L380.7,
177.7a19.3,19.3 0,0 1,10.7 25l-31.3,78.1a19.3,19.3 0,0 1,-25 10.7l-4,-1.6A19.3,19.3 0,0 1,320.3 264.9l31.3,-78.1A19.3,
19.3 0,0 1,376.6 176.1ZM210,390.3a19.2,19.2 0,0 1,-4.8 15.4a161.4 161.4,0 0,1 -38.4,-16.5l-9.9,-76.8a19.3,19.3 0,0 1,
16.6 -21.5l4.3,-0.6A19.3,19.3 0,0 1,199.3 306.9ZM391.7,323.9L390.3,330.3a163.1,163.1 0,0 1,-56.5 57.9l16.1,-73.5a19.3,
19.3 0,0 1,22.9 -14.7l4.2,0.9A19.3,19.3 0,0 1,391.7 323.9Z"/>

试一下,看看是否效果更好。


谢谢你的回答!然而,我尝试了你提供的XML文件,但它对渲染没有任何影响。你修改了Android路径还是SVG路径并进行了转换?也许AndroidStudio导入器本身无法识别跳过的命令,所以在转换之前尝试修改SVG文件会很好(如果这不是你已经做过的)。告诉我你的想法! - Francesco Ambrosini
1
我修改了VectorDrawable。我怀疑修改SVG不会有任何区别。我猜想是错误的直觉。 - Paul LeBeau
1
你说得完全正确。对于我的绘图,我只需要在一行(l)标签中包含它即可修复它。然而,在一个复杂的SVG中找到罪魁祸首就像在一堆针中找到一根针一样困难。在inkscape中的SVG输出设置中,请确保勾选“强制释放命令”并选择路径字符串格式为绝对。 - AaA

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接