Android中vector用法详解

    xiaoxiao2021-03-25  117

    在安卓的发展历程中,由于设备碎片化的原故,谷歌在app中图标的适配上做出一步又一步的改进,大体有这么几个阶段:

    首先有了drawable-(m|h|xh|xxh|xxxh)dpi自android studio后,又有了mipmap-(m|h|xh|xxh|xxxh)dpi随着android L的发布,带来了VectorDrawable,矢量图的支持

    第一种方案大家都很熟悉, 但也是我们头痛的地方,因为每种icon都需要出几套不同分辨率,这无形的增加了app的容量,而且也增加了美工和开发人员的工作量,但是我们又不得不去做。 第二种是第一种的升级版, 没有实质上的区别,但是在缩放上提供了更好的性能和更少的内存占用。 第三种,矢量图,先大概解释下:矢量图在很久很久以前就已经应用起来了,是一种基于xml的图像,因为图片不提供具体的像素,只提供的是绘图的指令,所以好处是 占用内存非常小,性能高,可以任意缩放而不会失真,但是缺点也很明显,没有位图表达的色彩丰富。 然而现在app风格越来越扁平, 拟物化已经成了过去,矢量图成了越来越多人的选择。但是,Android和iOS对于矢量图的支持还非常弱.

    android在最新的支持包中,已经加入了向下兼容的库:VectorDrawableCompat和AnimatedDrawableCompat,关于这两点的介绍网上很多,但是大多相同,但是有坑。今天我就围绕这个上代码,让未上车的猿们抓紧时间上车。


    首先,去哪找合适的矢量图: 阿里巴巴UX矢量库 传送门

    找到你需要的图标,并下载svg

    在android中打开vector assert

    点击Local SVG 选择路径,并命名drawable文件名字

    就在drawable目录生成了如下图

    ok, 一张可以任意缩放的图片有了。 接着看怎么引用, 先讲解一下, android L 以后矢量图是以vectorDrawable的形式来使用了, 但是这个库只支持L以后的,于是谷歌出了一个兼容包: VectorDrawableCompat,AnimatedVectorDrawableCompat

    As you may have seen on the Support Lib 23.2.0 blog post, we now have compatible vector drawable implementations in the support libraries: VectorDrawableCompat and Animated VectorDrawableCompat.

    意思是说 在appcompat 23.2.0开始,提供了以上两种支持库一个用于兼容矢量图,但是这个支持库要使用的话,还得在app的gradle里面加个这样的配置:

    //在gradle2.0及以上: android { defaultConfig { vectorDrawables.useSupportLibrary = true }} //在gradle 1.5以前 android { defaultConfig { // Stops the Gradle plugin’s automatic rasterization of vectors generatedDensities = [] } // Flag to tell aapt to keep the attribute ids around aaptOptions { additionalParameters "--no-version-vectors" } } 12345678910111213141516 12345678910111213141516

    ok , 配置完毕,下一步是怎么使用

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="10dp" xmlns:app="http://schemas.android.com/apk/res-auto" > <android.support.v7.widget.AppCompatImageView android:layout_width="42dp" android:layout_height="42dp" app:srcCompat="@drawable/icon_shopping"/> </LinearLayout> 1234567891011121314151617 1234567891011121314151617

    ok , 可以使用,试着改变下图标大小,会发现,完全一样,没有一点模糊 。 这里要说到,这种的局限性: 1.只能用于AppCompatImageView或者AppCompatImageButton或其子类,而且必须在app:srcCompat标签中,额,那我要用在TextView,Button上怎么办?我试试:

    <android.support.v7.widget.AppCompatTextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:drawableLeft="@drawable/icon_shopping" android:text="我想要小图标"/> 123456 123456 Caused by: android.content.res.Resources$NotFoundException: File res/drawable/icon_shopping.xml from drawable resource ID #0x7f02004d at android.content.res.Resources.loadDrawable(Resources.java:2101) at android.content.res.TypedArray.getDrawable(TypedArray.java:602) at android.widget.TextView.<init>(TextView.java:806) at android.support.v7.widget.AppCompatTextView.<init>(AppCompatTextView.java:60) at android.support.v7.widget.AppCompatTextView.<init>(AppCompatTextView.java:56) 1234567 1234567

    嗯,除了一大堆错误,没有别的效果, 怎么办?

    You don’t have to use StateListDrawable. It also works with InsetDrawable, LayerDrawable, LevelListDrawable and RotateDrawable containers. The only rule is that the vector needs to be in a separate file.

    在android官方推文中找到这句话 , 意味着,我们要在普通控件上使用Vector,就必须依附于StateListDrawable,InsetDrawable,LayerDrawable,LevelListDrawable,RotateDrawable,所以我来试试?

    <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/icon_shopping"/> </selector> 1234 1234 <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:drawableLeft="@drawable/shopping_res" android:text="我想要小图标"/> 123456 123456

    结果,相信有些哥们也尝试到这里了, 仍然是一大堆的错误。。。嗯,不是说包在那几个drawable里面就可以用了吗?忽悠人?这个帖子就此结束? 不不不。

    First up, this functionality was originally released in 23.2.0, but then we found some memory usage and Configuration updating issues so we it removed in 23.3.0. In 23.4.0 (technically a fix release)* we’ve re-added the same functionality but behind a flag which you need to manually enable.*

    我英文不太好, 应该是说,在23.2.0中放出了这个功能,但是后来发现了一些bug ,在23.3.0里面又移除了,后来在23.4.0中修复这些bug , 但是我们没有默认开启了,你需要通过一个标志来启用,呵呵哒。。这就是报错的原因了。。

    If you want re-enable this, just stick this at the top of your Activity:

    static { AppCompatDelegate.setCompatVectorFromSourcesEnabled(true); } 123 123

    嗯,这句话简单, 就是说,你要想再用上, 就在你的activity里面加上这句来启用vector , 结果怎样呢?

    ok ~问题解决。嗯,到了这一步,我们已经可以自由的使用矢量图标了呢, 那怎么改变图标颜色呢?这个我要说声抱歉,我还没有想在xml里面设置图标背景的方法, 有人会说drawableTint,这个可以,但是只支持api23以上,嗯,所以: 1.对于vector,我只想到了在xml里面改变fillColor来改变颜色,但这样就不好了,几个颜色就要几个图片, 2.可以用代码在合适的位置设置:

    VectorDrawableCompat a = VectorDrawableCompat.create(getResources(), R.drawable.icon_shopping, getTheme()); a.setTint(Color.RED); //设置单一的颜色 a.setTintList(ColorStateList.valueOf(Color.RED));//设置状态性的,比如点击一个颜色,未点击一个颜色 123 123 DrawableCompat.setTint(a,Color.RED); //用这个v4提供的也可,这个适用于任意的drawable着色 1 1

    3.可以在AnimatedVectorDrawable中用动画来改变vector的颜色 , 嗯,第三个方案涉及的知识又多了起来, 这个可以再起一个博客详细来说,先略过。


    嗯,说好了爬坑,就不可能到这里就结束了。

    前面所说的这个矢量图只能用在AppcomatImageView,AppcompatImageButton, 但实际上,用ImageView,ImageButton加上app:srcCompat也行, 为什么?因为你用了appcomat后,它会自动的把你的一部分控件转成AppCompatXxx的控件。


    总结一下,这个矢量图的缺点吧:

    1.麻烦, 需要下载->vector asset转换->用在非imageview中还要再写一个xml包裹起来才可用 2.不能随心所欲的在xml布局中任意切换图标颜色 , 如果在vector的xml里面改fillcolor,则这个图标就不好复用了。我的意思则是一处创建,随意使用。 3.支持库正在更新的过程中, 可能出现各种各样bug,也可能出现前面改动api实现而掉坑的情况。 123 123

    那怎么办?怎么办? 前面介绍的 :

    阿里巴巴UX矢量库 传送门

    对,就是它。后面要介绍的

    iconfont

    它的原理是,把你想要的矢量图标打包成一个ttf,在android中应用这个ttf,就可以随心所欲了,怎么个随心所欲? 用TextView的setText设置图标, setTextSize设置大小, 用TextColor设置图标颜色 ,只要能显示String的控件,都可以用,这样说来如何 ?

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="10dp" xmlns:app="http://schemas.android.com/apk/res-auto" > <android.support.v7.widget.AppCompatImageView android:layout_width="42dp" android:layout_height="42dp" app:srcCompat="@drawable/icon_shopping"/> <android.support.v7.widget.AppCompatTextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:drawableLeft="@drawable/shopping_res" android:text="我想要小图标"/> <com.example.liufan.demo1.IconfontView android:layout_width="wrap_content" android:layout_marginTop="10dp" android:textSize="60sp" android:textColor="#f00" android:text="" android:layout_height="wrap_content" /> </LinearLayout> 123456789101112131415161718192021222324252627282930 123456789101112131415161718192021222324252627282930

    这个IconfontView,是继承自TextView,在初始化的时候加载了字体而已, & # xe725; 这个是上图图标的代码。 嗯,这个并不算是什么高科技, 只是一个字体而已, 我就不长篇大论了, 下面贴出获取的流程吧,图从官网拿的:

    选中一堆需要的图标并加入购物车, 然后再这里点下载到本地,

    其中iconfont.ttf就是我们需要的字体了, 其他的那些在web上用的, 可以忽略。把[* .ttf, .eot, .svg , *.woff]复制到项目中assets中,然后,

    public class IconfontView extends TextView { private static Typeface __cachedTypeFace = null; public IconfontView(Context context) { super(context); initFont(); } public IconfontView(Context context, AttributeSet attrs) { super(context, attrs); initFont(); } public IconfontView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initFont(); } private void initFont() { if (__cachedTypeFace == null) { final Typeface iconfont = Typeface.createFromAsset(getContext().getAssets(), "iconfont/iconfont.ttf"); __cachedTypeFace = iconfont; } setTypeface(__cachedTypeFace); } } 123456789101112131415161718192021222324252627 123456789101112131415161718192021222324252627

    这里就是初始化的时候指定一下字体 , 这个iconfont什么的, 这个我由于写的是demo就写死的, 这里可以自定义一个属性,用来指定具体要用的字体 。

    ok , 现在打开解压目录的demo.html

    每个图标下的& #xe000就是这个图标的代码, 可以在IconfontView的text中设置了, 看下效果,

    <com.example.liufan.demo1.IconfontView android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="" android:textColor="#f00" android:textSize="200sp" /> <com.example.liufan.demo1.IconfontView android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="" android:textColor="#f0f" android:textSize="200sp" /> 12345678910111213141516 12345678910111213141516

    好了, 就是这些了, 基本全面, 如果帮忙您,希望您能帮我顶起来让更多人看到, 如果说的有误,希望我能收到您的指正。

    (function () {('pre.prettyprint code').each(function () { var lines = (this).text().split(\n).length;var numbering = $(' ').addClass('pre-numbering').hide(); (this).addClass(hasnumbering).parent().append( numbering); for (i = 1; i
    转载请注明原文地址: https://ju.6miu.com/read-15221.html

    最新回复(0)