无效的可绘制标签矢量图。

44

我正在尝试在Android Lolipop之前的设备上使用矢量图。我按照这里的说明操作了,但仍然遇到崩溃问题。

build.gradle:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.0.0-beta6'
    }
}
apply plugin: 'com.android.application'

repositories {
    maven { url 'http://maven.android-forever.com' }
    jcenter()
}

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.2"

    defaultConfig {
        applicationId "com.test.app"
        minSdkVersion 16
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"
        vectorDrawables.useSupportLibrary = true
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.2.0'
    compile 'com.android.support:design:23.2.0'
    compile "de.greenrobot:eventbus:2.4.0"
    compile 'de.greenrobot:greendao:2.1.0'
    compile "com.af:android-utility:1.0.0.9"
    compile project(':volleyplus')
    compile project (':libvlc')
}

三角形.xml:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/triangle_v"/>
</selector>

triangle_v.xml

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

<path
    android:name="triangle"
    android:fillColor="#FF0000"
    android:pathData="m 50,0 l 50,100 -100,0 z"/>

</vector>

布局.xml

<ImageView
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:background="@drawable/triangle"/>

我还尝试过使用app:srcCompat,但是这种情况下,可绘制物就是不显示。


1
我注意到在selector中使用向量和作为布局背景会导致这些异常。 - Someone Somewhere
14个回答

35

在加载选择器上的矢量图形时,在 Android 5.0 以下的设备中也会遇到此问题:

在你的 onCreate 方法中使用 AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)

设置是否可以在较旧的平台(<API 21)上使用 android.graphics.drawable.DrawableContainer 资源中的矢量图形。 启用后,AppCompat 可以拦截一些来自框架的可绘制物膨胀,从而启用了隐式膨胀 android.graphics.drawable.DrawableContainer 资源中的矢量图形。

protected final void onCreate(Bundle savedInstanceState) {
         AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
         super.onCreate(savedInstanceState);
         ...

4
即使我使用了'app:srcCompat',我仍然遇到了这个问题,但是这个答案解决了我的问题。 - Ratul
1
这解决了我的烦恼。 - Ceddy Muhoza
1
这对我没有解决问题。 - fobbymaster
1
对我来说没有解决问题,只在版本小于21的情况下出现这个问题。 - Kaustubh Bhagwat

33

如果使用vector,请确保以下代码中有如下设置:
vectorDrawables.useSupportLibrary = true

同时将android:src改为app:srcCompat

例如:

<ImageView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:src="@drawable/triangle"/>

为了

<ImageView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:srcCompat="@drawable/triangle"/>

2
这个答案帮了我很多。为了更清晰明了,进行了编辑。原作者应该得到更好的评价而不是两个踩。 - RobLabs
3
这是真正的答案!除非你真的忘记扩展AppCompatActivity,否则不应该是其他答案。 - Matthieu Smith

27
我遇到了类似的问题,@pedja提供的答案很有用。总的来说,在Chris Banes关于矢量图兼容性的文章中提到,支持库通过在pre-L版本中注入其版本的ImageView并进行一些钩子操作来实现兼容。这隐含地要求使用AppCompat类的版本,例如AppCompatActivity
在我的情况下,矢量图在一个类似toast的独立视图中使用,没有关联的activity,并使用应用程序上下文。最终,我直接在xml布局定义中使用了AppCompatImageView,即像下面这样:
<android.support.v7.widget.AppCompatImageView
             android:id="@+id/some_id"
             android:layout_width="24dp"
             android:layout_height="24dp"
             android:src="@drawable/selector_referencing_vector_drawable"/>
因此,不需要使用神奇的“hook”机制。 经过测试,这也适用于 Activity 类,无需使用 AppCompatActivity 。 所有上述操作都没有升级到23.2.1版本,该版本解决了不同的问题。

5
不,你应该使用app:srcCompat而不是android:src,以便在Lollipop之前的版本中使用矢量图形。 - WindRider
19
是我自己的问题还是谷歌工程师忘了提供TextView drawable的兼容解决方案?比如说 android:drawableLeft="@drawable/somevector" - QED
我通过在onCreate(...)方法中添加AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);来解决了drawableLeft问题,然后通过setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(<drawable_id>), null, null, null)以编程方式设置可绘制对象。 - r4m

19

问题在于我的活动没有扩展AppCompatActivity,而是普通的Activity

这在支持矢量图形的任何文档/示例中都没有指定。


14
这里给出的答案忽略了一个情况,即当您想将可绘制对象添加到TextView时,因为它会导致相同的错误。在我的情况下,我有

<TextView .... android:drawableLeft="some_vectore_drawable" />

我找不到解决办法,所以我从XML代码中删除了那一行,并以这种方式将其放入我的Java代码中

Drawable somevectordrable = AppCompatDrawableManager.get().getDrawable(context, R.drawable.somevectordrawable);
mytextview.setCompoundDrawableWithIntrinsicBounds(somevectordrable, null, null, null);

关于代码的澄清:

  1. 使用AppCompatDrawableManager从drawables文件夹中获取矢量图形

  2. 将刚刚获取的可绘制对象设置为我们的textview左侧drawable


这对我很有用。我升级到Gradle 3,然后在所有4.n设备上开始看到崩溃。解决方法是对于所有早于Lollipop的设备使用:AppCompatDrawableManager.get().getDrawable(this, R.drawable.arrow);而不是ContextCompat.getDrawable(this, R.drawable.arrow); - etherton
1
它会发出警告:AppCompatDrawableManager 只能从同一库组内调用。 - Nainal
@Nainal,也许是谷歌的代码有所改变,去年我尝试时没有收到警告,这个回答发布的时间大约就是那个时候。 - Tsepo Nkalai
@Albert Vila Calvo已经回答了如何在xml本身中完成此操作的问题。 - Lahiru Chandima

8
这是我在互联网上找到的全部内容,对我很有用。检查一下你是否遗漏了其中的任何一个。
1)在 build.gradle 文件中:
 android {
        ...
        defaultConfig {
            ...
            vectorDrawables.useSupportLibrary = true
        }
  }

2) 必须使用类似版本号的 buildToolsVersion '27.0.3'compile 'com.android.support:appcompat-v7:27.0.3'

3) 使用高于3的 gradle 版本
classpath 'com.android.tools.build:gradle:3.0.1'

4) 对于 ImageView,请使用 app:srcCompat

xmlns:app="http://schemas.android.com/apk/res-auto"
app:srcCompat="@drawable/ic_logo"

5) 但是如果您需要 android:drawableLeft 或者 android:drawableRigth 等等,则需要:

ic_logo.xml(矢量 XML)

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:width="@dimen/home.button.icon"
    android:height="@dimen/home.button.icon"
    android:viewportWidth="24.0"
    android:viewportHeight="24.0"
    tools:ignore="VectorRaster">
    <path
        android:fillColor="#FFFFFF"
        android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"/>
</vector>

ic_logo_select.xml(矢量选择器)
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_checked="true"
        android:drawable="@drawable/ic_logo" />
    <item android:drawable="@drawable/ic_logo" />
</selector>

现在您可以使用android:drawableLeftandroid:drawableRight
<android.support.v7.widget.AppCompatButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:drawableLeft="@drawable/ic_logo_select"/>

6) 最后,在加载主方法之前的静态方法中设置setCompatVectorFromResourcesEnabled = true。

public class MainActivity extends AppCompatActivity {
     static {
            AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
     }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ....
    }
}

1
我曾经为drawableLeft和drawableTop而苦恼,但是你的解决方案真正起作用了。谢谢! - Martin Macheiner
这是一个很棒的答案...应该被选为答案...它完美地工作了。谢谢伙计。 - Zia Ur Rahman
请注意,对于 drawableLeftdrawableRight,您不需要 <item android:state_checked="true" android:drawable="@drawable/ic_logo" /> 这一项。只有 <item android:drawable="@drawable/ic_logo" /> 就足够了。 - Albert Vila Calvo

6
您还需要包含新的向量支持库:
compile 'com.android.support:support-vector-drawable:23.2.0'

7
不行,通过设置 vectorDrawables.useSupportLibrary = true 可隐式地包含该库。 - pedja

6

它可以与23.2.0或23.4.0一起使用,但不能与23.3.0一起使用。谷歌太不严肃了!

首先,这个功能最初是在23.2.0中发布的,但后来我们发现了一些内存使用和配置更新问题,所以在23.3.0中将其删除了。在23.4.0(技术上是一个修复版本)中,我们重新添加了相同的功能,但需要手动启用标志。

参考: https://medium.com/@chrisbanes/appcompat-v23-2-age-of-the-vectors-91cbafa87c88#.waicp19gh


这是正确的方法:使用带有srcCompat的AppCompatImageView。 - Igor Vuković

4
如果您在使用drawableLeftdrawableRightdrawableTopdrawableXxx等时遇到异常问题,并且您的项目的buildToolsVersion > 26.0.2。请检查您的应用级gradle文件,如果存在vectorDrawables.useSupportLibrary = true,请删除它,然后这个崩溃就会消失。
这是因为自26.0.2之后,buildTools将处理矢量资源,但与vectorDrawables.useSupportLibrary=true冲突。
测试日期:2019/03/27。
(如果您在应用级gradle文件中找不到buildToolsVersion,则表示您正在使用Gradle 3.0.0或更高版本的Android插件,您的项目会自动使用插件指定的默认版本的构建工具。在这种情况下,您的buildToolsVersion已经大于26.0.2)。

3

令我惊讶的是这里还没有提到这个问题。

这种崩溃经常发生在以下情况下:

android:drawableRight
android:drawableLeft
android:drawableTop
android:drawableBottom
android:drawableStart
android:drawableEnd

通常的解决方案是创建一个包装原drawable的可绘制对象,并使用 <selector><item android:drawable=""></selector> 标记,或者使用代码设置复合可绘制对象。但现在你可以使用如下方式:

app:drawableRightCompat
app:drawableLeftCompat
app:drawableTopCompat
app:drawableBottomCompat
app:drawableStartCompat
app:drawableEndCompat

这个功能是在appcompat 1.1.0-alpha01中添加到AppCompatTextView中的。

为了使用这个属性,我必须使用AppCompat视图而不是普通的视图,例如,我使用了AppCompatButton代替了Button


不确定是否需要使用vectorDrawables.useSupportLibrary trueAppCompatDelegate.setCompatVectorFromResourcesEnabled(true)(我两个都有)。可以参考Nick Butcher的这篇文章:https://medium.com/androiddevelopers/using-vector-assets-in-android-apps-4318fd662eb9.


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