Android5.0以下矢量图兼容问题探究

原文链接:
https://blog.csdn.net/u014750748/article/details/82621906

Android5.0以下矢量图兼容问题探究
关于如何使用矢量图的方法网上一抓一大把,无非就是在defaultConfig加上一句vectorDrawables.useSupportLibrary = true 和在BaseActity加上一句

static {       
   AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}

然后我们就开始兴冲冲的使用这个高大上的矢量图。然而,使用类似TextView的drawableLeft或者drawableRight属性的时候,在5.0设备以下直接就崩溃,报出类似以下的错误。

Caused by: org.xmlpull.v1.XmlPullParserException: Binary XML file line #2: invalid drawable tag vector
        at android.graphics.drawable.Drawable.createFromXmlInner(Drawable.java:877)
        at android.graphics.drawable.Drawable.createFromXml(Drawable.java:818)
        at android.content.res.Resources.loadDrawable(Resources.java:1920)
        at android.content.res.TypedArray.getDrawable(TypedArray.java:601) 
        at android.widget.TextView.<init>(TextView.java:622) 
        at android.support.v7.widget.AppCompatTextView.<init>(AppCompatTextView.java:87) 
        at android.support.v7.widget.AppCompatTextView.<init>(AppCompatTextView.java:83)

WTF???说好的兼容就是这样的?无效的vector标签?网上找了找解决方案,无非以下两种。

1、在build.gradle的android标签中加入如下代码。

aaptOptions {  
    additionalParameters "--no-version-vectors"  
}

这种方法会根据矢量图生成一套兼容低版本的对应的png的图片的方式,兼容5.0以下设备。嗯?这不是把Apk体积变得更大了吗?那我还用毛的矢量图?

2、将矢量图包裹在其他标签中
类似这样子。

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

WTF?这么多矢量图都得手动写一个对应的文件,作为一个有追求的程序员这怎么忍?

3、一劳永逸的自创解决方案
为什么ImageView可以在Android5.0以下正常的使用矢量图?首先要明白,在我们使用AppCompatActivity的时候,xml里面定义的ImageView会被自动替换AppCompatImageView,这就是为什么我们在xml里面定义ImageView里面的android:src属性设置为矢量图的时候会报错,让我们替换为app:srcCompat。我们找到ApppCompatImageView的源码,查看一下它是怎么解析矢量图的,我们的问题不久迎刃而解了吗? 
查看源码后得知,它是通过一个叫AppCompatImageHelper的类去辅助加载矢量图的,找到核心的加载矢量图的代码如下。

Drawable d = AppCompatResources.getDrawable(this.mView.getContext(), resId);
if (d != null) {
    DrawableUtils.fixDrawable(d);
}

找到核心的方法就简单了,我们封装一个工具类去加载图片,然后自定义一个TextView,自定义一个drawableLeftCompat和drawableLeftCompat属性,按照上序代码去加载图片,然后赋值给本身的drawableLeft和drawableRight。

 

相关链接:https://blog.csdn.net/u010577768/article/details/79352731

点赞