Android 自定義 svg 顏色

1、XML 設(shè)定顏色

  <vector android:height="24dp" android:viewportHeight="1024"
    android:viewportWidth="1024" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
    <path android:fillColor="#FFF" android:pathData="M395.22,513.6l323.14,-312.37c19.05,-18.42 19.05,-48.27 0,-66.66 -19.05,-18.42 -49.91,-18.42 -68.96,0L291.75,480.29c-19.05,18.42 -19.05,48.27 0,66.66l357.63,345.69c9.53,9.21 22.01,13.8 34.5,13.8 12.49,0 24.97,-4.59 34.47,-13.83 19.05,-18.42 19.05,-48.24 0,-66.66L395.22,513.6z"/>
  </vector>

xml設(shè)定顏色很簡單,fillColor 這個(gè)attr即可設(shè)定。

2、kotlin代碼動(dòng)態(tài)設(shè)定顏色

先構(gòu)造一個(gè)適用的對(duì)象

/**
 * svg 圖片需要構(gòu)建的對(duì)象
 */
data class InitImgRes(
        @DrawableRes val imgRes: Int,
        @ColorRes val colorRes: Int,
        val imageView: ImageView,
        val context: Context
)

一般很多博客是這樣寫的:

   /**
     * 給imageView 的svg初始化顏色
     */
    fun initSvgColor(initImgRes: InitImgRes){
        // 獲取該image的資源
        val res  = initImgRes.context.resources
        // 獲取該image的主題對(duì)象
        val theme = initImgRes.context.theme
        //創(chuàng)造vectorDrawable工具對(duì)象,影響vectorView繪制
        val vectorDrawableCompat = VectorDrawableCompat.create(res,initImgRes.imgRes,theme) ?: return
        // 使用Tint上色
        if (Build.VERSION.SDK_INT>22)
        vectorDrawableCompat.setTint(res.getColor(initImgRes.colorRes,theme))
        else vectorDrawableCompat.setTint(res.getColor(initImgRes.colorRes))
        initImgRes.imageView.setImageDrawable(vectorDrawableCompat)
    }

VectorDrawableCompat create源碼如下:

   @Nullable
    public static VectorDrawableCompat create(@NonNull Resources res, @DrawableRes int resId, @Nullable Theme theme) {
        if (VERSION.SDK_INT >= 24) {
            VectorDrawableCompat drawable = new VectorDrawableCompat();
            drawable.mDelegateDrawable = ResourcesCompat.getDrawable(res, resId, theme);
            drawable.mCachedConstantStateDelegate = new VectorDrawableCompat.VectorDrawableDelegateState(drawable.mDelegateDrawable.getConstantState());
            return drawable;
        } else {
            try {
                XmlPullParser parser = res.getXml(resId);
                AttributeSet attrs = Xml.asAttributeSet(parser);

                int type;
                while((type = parser.next()) != 2 && type != 1) {
                    ;
                }

                if (type != 2) {
                    throw new XmlPullParserException("No start tag found");
                }

                return createFromXmlInner(res, parser, attrs, theme);
            } catch (XmlPullParserException var6) {
                Log.e("VectorDrawableCompat", "parser error", var6);
            } catch (IOException var7) {
                Log.e("VectorDrawableCompat", "parser error", var7);
            }

            return null;
        }
    }
調(diào)用影響state方法.png

根據(jù)源碼,我們不難看出在24之前,通過drawable的xml解析,來上色,這樣效率非常低,再通過24之后的版本,自建了一個(gè)drawable對(duì)象,在此對(duì)象中運(yùn)行影響VectorView的state這樣造成的后果是,VectorView的state永遠(yuǎn)賦值,當(dāng)前xml下的svg永遠(yuǎn)上色為最后一個(gè)顏色。故拋棄此類寫法


正確代碼寫法:

    /**
     * 給imageView 的svg初始化顏色
     */
    fun initSvgColor(initImgRes: InitImgRes){
        //利用ContextCompat工具類獲取drawable圖片資源
        val drawable = ContextCompat.getDrawable(initImgRes.context, initImgRes.imgRes)?:return
        //簡單的使用tint改變drawable顏色
        val drawableResult = tintDrawable(drawable,ContextCompat.getColor(initImgRes.context, initImgRes.colorRes))
        initImgRes.imageView.setImageDrawable(drawableResult)
    }

    /**
     * 給drawable上色 
     */
     private fun  tintDrawable( drawable:Drawable, colors:Int): Drawable {
        val wrap = DrawableCompat.wrap(drawable).mutate()
        DrawableCompat.setTint(wrap,colors)
        return wrap
    }

再查看源碼:

mutate方法源碼解釋.png

源碼注釋告訴了我們:此獲取的drawable不與其他drawable 共享,簡而言之,就是構(gòu)建單獨(dú)的內(nèi)存模塊來存儲(chǔ)此drawable達(dá)到相互不影響的狀態(tài)。

此種寫法代碼量減少的很明顯,很能理解,先直接獲取svg 的drawable 對(duì)象,然后通過預(yù)設(shè)資源,獲取顏色進(jìn)而給當(dāng)前對(duì)象上色即可,不需要影響vectorView繪制。推薦使用。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,119評(píng)論 25 708
  • 用兩張圖告訴你,為什么你的 App 會(huì)卡頓? - Android - 掘金 Cover 有什么料? 從這篇文章中你...
    hw1212閱讀 14,030評(píng)論 2 59
  • 作文要求:寫你印象深刻的一個(gè)星期天,在記敘中要寫出自己的感受。做到內(nèi)容具體,語句通順,標(biāo)點(diǎn)正確,書寫工整。題目:那...
    死侃腦殼的老妖婆閱讀 1,191評(píng)論 7 9
  • 最近三個(gè)月,每天急于干活,為了把學(xué)校售貨機(jī)的品種調(diào)整到學(xué)生喜歡的頻率,想辦法提高營業(yè)額,就象學(xué)生為了考出好成績,每...
    綠禾心理咨詢催眠療愈閱讀 247評(píng)論 0 0
  • “在微信公眾號(hào)平臺(tái)推送一篇邀請(qǐng)女人們回憶有關(guān)她們前任的話題文章,從報(bào)名的粉絲中選出幾位進(jìn)行采訪,將訪談的結(jié)果記錄下...
    王偉應(yīng)閱讀 350評(píng)論 0 3

友情鏈接更多精彩內(nèi)容