矢量图:无效的可绘制标签渐变

24

我已经使用Android Asset Studio一段时间了,从Zeplin导出SVG文件生成矢量图标。除了偶尔出现的一些问题,它都工作得很好。但今天当我尝试使用生成的矢量图标时,出现了一个异常。

android.view.InflateException: Binary XML file line #0: Error inflating class <unknown>

并且在相同的堆栈跟踪中:

Caused by: org.xmlpull.v1.XmlPullParserException: Binary XML file line #0: invalid drawable tag gradient

我对Android中的矢量可绘制对象和SVG并不了解。在矢量可绘制对象中不支持渐变吗?有没有解决这个问题的方法或者我需要使用PNG格式的图片?

我正在使用支持库版本:

com.android.support:support-v4:26.1.0

我正在使用

Android Studio 3.0

这是由Android Asset Studio生成的VectorDrawable文件:

<vector 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:aapt="http://schemas.android.com/aapt"
    android:width="360dp"
    android:height="110dp"
    android:viewportWidth="360.0"
    android:viewportHeight="110.0">
    <path
        android:pathData="M82,46H0v64h360V46h-81.88v-0.3h-26.21c-14.25,0 -38.69,-6.2 -46.95,-25.93C200.99,10.25 193.27,0.52 180,0.47c-13.27,-0.05 -20.04,9.24 -24.75,19.3 -8.22,17.55 -24.66,26.19 -49.34,25.93H82V46z"
        android:fillType="evenOdd">
        <aapt:attr name="android:fillColor">
            <gradient 
                android:startY="0.41999998688697815" 
                android:startX="0.0" 
                android:endY="110.0" 
                android:type="linear" 
                android:endX="360.0">
                <item android:offset="0.0" android:color="#FFCB09FF" />
                <item android:offset="1.0" android:color="#FF8A06FF" />
            </gradient>
        </aapt:attr></path>
</vector>

原始SVG文件链接:https://drive.google.com/file/d/1Lj62xJv5IpYR5Lle7w1kMsFXh6y5PijK/view?usp=sharing

在Sublime中打开的SVG内容:

<svg xmlns="http://www.w3.org/2000/svg" width="360" height="110" viewBox="0 0 360 110">
    <defs>
        <linearGradient id="a" x1="0%" y1="0%" y2="100%">
            <stop offset="0%" stop-color="#CB09FF"/>
            <stop offset="100%" stop-color="#8A06FF"/>
        </linearGradient>
    </defs>
    <path fill="url(#a)" fill-rule="evenodd" d="M82 46H0v64h360V46h-81.876v-.299h-26.208c-14.25 0-38.69-6.198-46.946-25.93C200.99 10.252 193.27.52 180 .474c-13.27-.047-20.04 9.238-24.75 19.295-8.217 17.55-24.662 26.194-49.336 25.931H82V46z"/>
</svg>

1
这可能是Android Studio中的此错误。您是否有一个可以发布在某个地方以重现此问题的SVG?另外,您使用的是哪个版本的Android Studio? - CommonsWare
1
抱歉,我的意思是输入SVG,而不是矢量资产输出。 - CommonsWare
1
好的,我的转换后的资源看起来和你的一样。但是我在一个minSdkVersion 21的项目中将该资源用于ImageView上,在运行Android 7.1的Nexus 9上没有问题。你在哪个版本的Android上测试时出现了崩溃? - CommonsWare
3
好的,我认为这应该是一个单独的错误。我利用你的SVG创建了一个示例项目,并提交了一个缺陷报告。至少,向量图像向导应该更好地处理这个问题,如果生成的向量可绘制对象不能在我们的“minSdkVersion”上工作,至少应该警告我们。我的假设是,Android 7.0只添加了<gradient>支持(因为来自你的SVG的资产在那里有效)。 - CommonsWare
7
关于解决方法,您可以使用其他工具将SVG转换为PNG格式,将矢量可绘制对象从“res/drawable/”移动到“res/drawable-anydpi-v24/”,并使用图像资源向导设置适当密度的PNG版本。在Android 7.0上使用矢量图像,在5.0-6.0上则使用PNG图像。 - CommonsWare
显示剩余9条评论
10个回答

25

这个解决方案在我们的 build.gradle 中运作良好。

defaultConfig {
vectorDrawables.useSupportLibrary = true
}

当使用带有渐变的矢量图形设置 ImageView 时,使用 app:srcCompat 替代 android:src


1
如果您尝试将此用于“ImageButton”,请确保使用androidx.appcompat.widget.AppCompatImageButton - SqAR.org
1
另外,不要忘记将 android:drawableStart 及其相关项替换为其兼容版本,例如 app:drawableStartCompat。 - Arpit J.

21

属性 android:fillColor 仅支持OS 7.0+,

android:fillColor 指定用于填充路径的颜色。可以是一个颜色或者(SDK版本为24或更高版本)一个颜色状态列表或渐变颜色(请参见GradientColor和GradientColorItem)。如果此属性被动画化,则动画设置的任何值都将覆盖原始值。如果未指定此属性,则不会绘制路径填充。

对于旧版本,我们可以在目录/drawable 中放置没有渐变的矢量素材,例如:

<vector android:height="24dp" android:viewportHeight="651.95"
    android:viewportWidth="531.48" android:width="24dp"
    xmlns:aapt="http://schemas.android.com/aapt" xmlns:android="http://schemas.android.com/apk/res/android">
    <path android:pathData="M386.8,30.2c-48.5,0 -76.1,18 -121.1,18s-72.6,-18 -121.1,-18c-87.9,0 -144.7,83.3 -144.7,186 0,92.9 160,350.5 265.7,350.5 112.9,0 265.7,-257.6 265.7,-350.5C531.5,113.5 474.7,30.2 386.8,30.2Z">
        <!--<aapt:attr name="android:fillColor">
            <gradient android:endX="212457.73219299316"
                android:endY="440836.2612554932"
                android:startX="212457.73219299316"
                android:startY="92857.94223999024" android:type="linear">
                <item android:color="#FFFC3A11" android:offset="0.0"/>
                <item android:color="#FFDA0300" android:offset="1.0"/>
            </gradient>
        </aapt:attr>-->
    </path>
    ...
    ...

并且在 /drawable-24 目录内使用渐变色:

<vector android:height="24dp" android:viewportHeight="651.95"
    android:viewportWidth="531.48" android:width="24dp"
    xmlns:aapt="http://schemas.android.com/aapt" xmlns:android="http://schemas.android.com/apk/res/android">
    <path android:pathData="M386.8,30.2c-48.5,0 -76.1,18 -121.1,18s-72.6,-18 -121.1,-18c-87.9,0 -144.7,83.3 -144.7,186 0,92.9 160,350.5 265.7,350.5 112.9,0 265.7,-257.6 265.7,-350.5C531.5,113.5 474.7,30.2 386.8,30.2Z">
        <aapt:attr name="android:fillColor">
            <gradient android:endX="212457.73219299316"
                android:endY="440836.2612554932"
                android:startX="212457.73219299316"
                android:startY="92857.94223999024" android:type="linear">
                <item android:color="#FFFC3A11" android:offset="0.0"/>
                <item android:color="#FFDA0300" android:offset="1.0"/>
            </gradient>
        </aapt:attr>
    </path>
    ...
    ...

7
我只想提醒一下。我使用Android Studio创建了一个包含渐变的SVG文件,并通过'New Vector Asset'进行制作。我构建了发布APK并查看了文件....在build>generated>res>pngs>release中,有drawable-anydpi-v24和xml文件已放置在那里。同样,在同一级别的drawable-*dpi中也有具有相同名称的png位图。因此,AS已处理向后兼容性,在理论上不应该发生任何设备上的崩溃。然而,在一个相当低的体积应用中,LG G4在一周后发生了一个崩溃。 - androidguy
1
@androidguy,你找到原因了吗?我也遇到了同样的问题,只有从LG G4 Android 6.0设备接收到崩溃报告。 - BakaWaii
@BakaWaii我想不出任何原因,但得出结论:LG只是有着可怕的错误代码。 我实施的解决方法是:从我之前评论中的路径中获取生成的PNG,将它们复制到实际src内的drawable-*dpi文件夹中,并删除drawable内的矢量.xml。 - androidguy

8

7

我通过使用以下方法解决了这个问题

app:srcCompat="@drawable/ic_vector"

替代

android:src="@drawable/ic_vector"

这在API 22设备上进行了测试。


谢谢,这在Android 5.1上运行良好。 - Gold.strike

5
由android:fillColor属性引起的错误,是因为:
android:fillColor指定用于填充路径的颜色。可以是颜色,也可以是SDK 24+中的颜色状态列表或渐变颜色(请参阅GradientColor和GradientColorItem)。如果此属性被动画化,则任何由动画设置的值都会覆盖原始值。如果未指定此属性,则不会绘制任何路径填充。
如果您想在早于24的版本中使用渐变,可以使用以下解决方法:
- 编辑您的矢量图形(例如称为drawable/ic_vector.xml):
<vector 
xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:aapt="http://schemas.android.com/aapt"
android:width="360dp"
android:height="110dp"
android:viewportWidth="360.0"
android:viewportHeight="110.0">
<path
    android:pathData="M82,46H0v64h360V46h-81.88v-0.3h-26.21c-14.25,0 -38.69,-6.2 -46.95,-25.93C200.99,10.25 193.27,0.52 180,0.47c-13.27,-0.05 -20.04,9.24 -24.75,19.3 -8.22,17.55 -24.66,26.19 -49.34,25.93H82V46z"
    android:fillType="evenOdd">
    <!--<aapt:attr name="android:fillColor">
        <gradient 
            android:startY="0.41999998688697815" 
            android:startX="0.0" 
            android:endY="110.0" 
            android:type="linear" 
            android:endX="360.0">
            <item android:offset="0.0" android:color="#FFCB09FF" />
            <item android:offset="1.0" android:color="#FF8A06FF" />
        </gradient>
    </aapt:attr></path>-->

创建另一个drawable资源,在其中插入渐变作为项目:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
    <shape android:shape="rectangle">
        <gradient 
            android:type="linear"
            android:startColor="#FFCB09FF"
            android:endColor="#FF8A06FF"
            android:angle="270">
        </gradient>
    </shape>
</item>
<item android:drawable="@drawable/ic_vector"/>

希望我已经对你有所帮助!


0

SVG中的渐变标签支持从操作系统版本7及以上。尝试在低于操作系统版本7的版本中注释掉渐变标签。


0

对我来说解决方案是不同的,我会在这里添加,希望能帮助其他人。

我正在使用一个带有梯度的向量,这里是一个示例:

<path android:pathData="M69.12,78.34">
<aapt:attr name="android:fillColor">
    <gradient
        android:centerX="69.12"
        android:centerY="78.34002"
        android:gradientRadius="0"
        android:type="radial">
        <item
            android:color="#FFFFF176"
            android:offset="0.41" />
        <item
            android:color="#FFFFC400"
            android:offset="1" />
    </gradient>
</aapt:attr>
</path>

请注意 android:gradientRadius="0",问题是,可能某些 Android 版本将其读作 null 并因此崩溃。我的解决方法是将其更改为 android:gradientRadius="0.1" 或任何其他小数值。

0

为了向后兼容,请使用

app:drawableStartCompat


0

看起来这个答案已经过时了。解决这个问题的最好方法是在 build.gradle 中配置正确的支持。

    defaultConfig {
       vectorDrawables.useSupportLibrary = true
    }

最近我创建了一个插件,可以自动从Zeplin下载资源并将它们转换为矢量可绘制图形。如果你想尝试,可以在这里找到更多详细信息。


-1
尝试在您的应用gradle中添加矢量支持命令,例如:
defaultConfig {
    vectorDrawables.useSupportLibrary = true
}

enter image description here


1
我已经在我的Gradle中有这个了。这个问题主要只是Asset Studio中的一个bug。它可以在7.0+上工作,但在5.0-6.*上会崩溃。 - Praveen Singh
1
这并没有帮助 :( - Jorgesys
如果你使用app:srcCompat而不是android:src,它就能正常工作。对于imageButton,你需要使用androidx.appcompat.widget.AppCompatImageButton - SqAR.org

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