android svg图片使用 vector

刚出来的时候好像用vector图片还得gradle配置,代码里配置,现在好像都不需要了,直接可以用了,简单复习下

必须

app的build.gradle里还是得加上这个
不加的话虽然vector图片可以识别,可是发现会模糊

defaultConfig{
//...
vectorDrawables.useSupportLibrary=true
}
  1. 导入图片
    系统提供了一些默认的,也可以用自己写的svg文件
image.png

然后看到下图,有两种,
默认系统的,点击红框的部分可以选择别的图片,点击local file就可以选择本地的svg图片,系统会自动转换的,完事next就ok


image.png

之后在drawable下就看到对应的xml文件

你不想用系统的,也不想导入svg文件,也可以自己新建一个,自己修改xml文件


image.png
  1. 简单分析下vector图片的属性
    下边就是个三角形
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24"
    android:viewportHeight="24">
    <path
        android:fillColor="#000"
        android:pathData="M7,14 l5,-5 5,5z" />
</vector>
image.png

width和heigth其实可以说是画布的大小。viewportWidth相当于把画布分为24份了。

path,简单看下,fillcolor填充颜色没啥说的。

pathData就是主要的。M移动到某个位子。如图x7y14,之后小写的l表示相对距离,x方向5,y方向-5也就是往上,之后又来个5,5其实是省略了一个小写的l。相同属性的可以省略,所以这里省略了l。最后一个z表示闭合。就是终点自动连接到起点完事。

支持的指令:

M = moveto(M X,Y) :将画笔移动到指定的坐标位置

L = lineto(L X,Y) :画直线到指定的坐标位置

H = horizontal lineto(H X):画水平线到指定的X坐标位置

V = vertical lineto(V Y):画垂直线到指定的Y坐标位置

C = curveto(C X1,Y1,X2,Y2,ENDX,ENDY):三次贝赛曲线

S = smooth curveto(S X2,Y2,ENDX,ENDY)

Q = quadratic Belzier curve(Q X,Y,ENDX,ENDY):二次贝赛曲线

T = smooth quadratic Belzier curveto(T ENDX,ENDY):映射

A = elliptical Arc(A RX,RY,XROTATION,FLAG1,FLAG2,X,Y):弧线

Z = closepath():关闭路径

使用原则:

坐标轴为以(0,0)为中心,X轴水平向右,Y轴水平向下

所有指令大小写均可。大写绝对定位,参照全局坐标系;小写相对定位,参照父容器坐标系

指令和数据间的空格可以省略

同一指令出现多次可以只用一个

注意,'M'处理时,只是移动了画笔, 没有画任何东西。 它也可以在后面给出上同时绘制不连续线。

  1. 看另外一个demo
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp" 
    android:viewportWidth="12"
    android:viewportHeight="12">
    <path
        android:fillColor="#DD6F6F"
        android:strokeColor="#C51DE2"
        android:strokeWidth="0.5"
        android:trimPathStart="0.2" //截掉path开头的一部分,从0到1,影响的是stroke,还有个trimPathOffset影响的是solid
        android:strokeLineCap="round"
        android:strokeLineJoin="bevel"
        android:pathData="M6,0 l6,6 -6,6 -6,-6z" />
</vector>
image.png

这个viewoportWidth和width不一样,也就是24dp被分成了12份,而下边的path,数字大小也是对应这个12份的了,
也就是x12就是最右边,y12就是最下边了。

  1. 其他的属性

clip-path 对它后边的所有path起作用,效果类似交集

    <clip-path android:pathData="M3,3 h5 v5 h-5 z" android:name="xxxx"/>
    <path android:pathData="M6,2 h10 v10 h-10 v-10z" android:fillColor="#D31919"/>

因为clip-path对它后边所有的path起作用,那咋办?
group标签来了,这样就只对group里的生效了,另外group标签还带旋转,拉伸,平移属性可以操作

    <group >
        <clip-path android:pathData="M3,3 h5 v5 h-5 z" android:name="xxxx"/>
        <path android:pathData="M0,2 h10 v10 h-10 v-10z" android:fillColor="#D31919"/>
    </group>

    <path android:pathData="M6,6 h-5 v-3z" android:fillColor="#111111"/>
  1. Stroke
    下边这一堆是定义边框的属性了,Cap是首尾的处理,有3种,和paint里的一样
    Join也是paint里的属性,就是两条线交叉的地方咋处理,bevel尖角,round圆角,miter
        android:strokeWidth="1"
        android:strokeColor="#f00"
        android:strokeAlpha="0.5"
        android:strokeLineCap="round"
        android:strokeLineJoin="bevel"

下边这个干啥的,和上边的Join有关联的,LineJoin是bevel的时候

android:strokeMiterLimit="1"

如下,正常这样的


image.png

设置了android:strokeMiterLimit="1"以后这样了,当然了,如果这个值很大,超出了默认的尖角范围的话,那没啥作用了,只有弄个小的值,才能裁掉多余的尖角,额,这个值好像最小值是1?


image.png
  1. name
    还都可以起个名字,动画的时候可以根据名字处理path下的某个属性
android:name="xxx"
  1. trim
    简单来讲就是对原始path进行裁剪,offset是从起点开始的偏移量,TrimPathStart就是从哪里开始裁剪,得加上offset的量, trimPathEnd一样的道理,结束位置, 范围都是从0到1的,就是整个path的百分比
        android:trimPathStart="0.2"
        android:trimPathEnd="0.5"
        android:trimPathOffset="0.3"

举个例子
path是个半圆弧,从左到右的

    <path android:pathData="m10,20c0,5.523,4.477,10,10,10c5.523,0,10,-4.477,10,-10"
        android:strokeWidth="1"
        android:strokeColor="#f00"
        android:strokeAlpha="0.5"
        android:strokeLineCap="round"
        android:strokeLineJoin="bevel"
        android:fillAlpha="0.5"
        android:fillColor="@color/colorPrimary"
        android:fillType="evenOdd"/>
image.png

然后,我们加上trim属性,效果图就变了,很小的一段了,从圆弧的(0.3+0.2)开始,到(0.3+0.5)结束,我背景画了条绿色的半圆作为参考

        android:trimPathStart="0.2"
        android:trimPathEnd="0.5"
        android:trimPathOffset="0.3"

image.png

trim的作用比较大了,动画的时候动态修改这个,就可以显示隐藏path了,也可以动态的一点一点的显示出来.
注意
这里的trimPath 是有限制的,它只作用于path的第一段,如果pathData里有断开的多个path的话,那么是按第一段来算的。
如下图,trimPathEnd是0.5结果就是第一段的一半
image.png

代码也很简单,path是由4段断开的圆弧组成的

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="146dp"
    android:height="146dp"
    android:viewportWidth="146"
    android:viewportHeight="146">

    <path
        android:name="pathBg"
        android:pathData="M76,9c33.672,0,61,27.328,61,61
         M137,76c0,33.672,-27.328,61,-61,61
         M70,137c-33.672,0,-61,-27.328,-61,-61
         M9,70c0,-33.672,27.328,-61,61,-61"
        android:strokeWidth="18"
        android:strokeColor="@color/light_gray_bg" />
    <path
        android:name="pathFill"
        android:pathData="M76,9c33.672,0,61,27.328,61,61
         M137,76c0,33.672,-27.328,61,-61,61
         M70,137c-33.672,0,-61,-27.328,-61,-61
         M9,70c0,-33.672,27.328,-61,61,-61"
        android:trimPathEnd="0.5"
        android:strokeWidth="18"
        android:strokeColor="@color/colorPrimary" />

</vector>

使用中的问题

  1. 无法获取bitmap
    下边这种获取到的bitmap是null
    6.0如果有fillType的话,能获取到,其他版本获取不到
Bitmap bitmap= BitmapFactory.decodeResource(getResources(),R.drawable.ic_vector_pic);

解决办法:
① 换回png图片
②通过canvas画出来,后边有提供方法

  1. progress的图片一闪一闪的
    图片旋转一圈左右就会消失一瞬间,看着不舒服
        <ProgressBar
            android:id="@+id/pb_show"
            android:indeterminateDrawable="@drawable/simple_loading"
            android:layout_width="65dp"
            android:layout_height="65dp"/>
<?xml version="1.0" encoding="utf-8"?>
<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/ic_loading"
    android:pivotX="50%"
    android:pivotY="50%"/>

解决办法,
①把vectorDrawables.useSupportLibrary = false设置为false,然后发现图片正常不会闪一下了,
不过不靠谱,没有这属性的话,无法让vector图片拉伸不模糊,所以只能使用png图片
或者:
android:indeterminateDrawable直接使用静态的ic_loading图片,完事我们开启一个动画旋转progressbar
②靠谱的解决办法:
https://www.jianshu.com/p/9f3221179e3c
vector loading图片稍作修改,增加group标签,方便旋转,如下
ic_loading.xml

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="65dp"
    android:height="65dp"
    android:viewportWidth="65"
    android:viewportHeight="65">
    <group
        android:name="root"
        android:pivotX="32.5"
        android:pivotY="32.5">
        <path
            android:fillColor="#76FFE5"
            android:pathData="M32.24,11.96c-1.768,0 -3.12,-1.352 -3.12,-3.12V3.12c0,-1.768 1.352,-3.12 3.12,-3.12s3.12,1.352 3.12,3.12v5.72c0,1.664 -1.352,3.12 -3.12,3.12z" />
        <path
            android:fillColor="#0DBFBA"
            android:pathData="M32.24,64.48c-1.768,0 -3.12,-1.352 -3.12,-3.12v-5.72c0,-1.768 1.352,-3.12 3.12,-3.12s3.12,1.352 3.12,3.12v5.72c0,1.768 -1.352,3.12 -3.12,3.12z" />
        <path
            android:fillColor="#BBFFF2"
            android:pathData="M20.488,15.08c-1.04,0 -2.08,-0.52 -2.704,-1.56l-2.808,-4.888c-0.832,-1.456 -0.312,-3.432 1.144,-4.264 1.456,-0.832 3.432,-0.312 4.264,1.144l2.808,4.888c0.832,1.456 0.312,3.432 -1.144,4.264 -0.416,0.208 -1.04,0.416 -1.56,0.416z" />
        <path
            android:fillColor="#1BCEB8"
            android:pathData="M46.8,60.528c-1.04,0 -2.08,-0.52 -2.704,-1.56l-2.808,-4.888c-0.832,-1.456 -0.312,-3.432 1.144,-4.264 1.456,-0.832 3.432,-0.312 4.264,1.144l2.808,4.888c0.832,1.456 0.312,3.432 -1.144,4.264 -0.52,0.312 -1.04,0.416 -1.56,0.416z" />
        <path
            android:fillColor="#E1FFF9"
            android:pathData="M11.96,23.608c-0.52,0 -1.04,-0.104 -1.56,-0.416l-4.888,-2.808c-1.456,-0.832 -1.976,-2.808 -1.144,-4.264 0.832,-1.456 2.808,-1.976 4.264,-1.144l4.888,2.808c1.456,0.832 1.976,2.808 1.144,4.264 -0.624,1.04 -1.664,1.56 -2.704,1.56z" />
        <path
            android:fillColor="#26DBC0"
            android:pathData="M57.512,49.92c-0.52,0 -1.04,-0.104 -1.56,-0.416l-4.992,-2.808c-1.456,-0.832 -1.976,-2.808 -1.144,-4.264 0.832,-1.456 2.808,-1.976 4.264,-1.144l4.888,2.808c1.456,0.832 1.976,2.808 1.144,4.264 -0.52,1.04 -1.56,1.56 -2.6,1.56z" />
        <path
            android:fillColor="#F3FFFD"
            android:pathData="M8.84,35.36H3.12C1.352,35.36 0,34.008 0,32.24s1.352,-3.12 3.12,-3.12h5.72c1.768,0 3.12,1.352 3.12,3.12s-1.456,3.12 -3.12,3.12z" />
        <path
            android:fillColor="#2EE5C6"
            android:pathData="M61.36,35.36h-5.72c-1.768,0 -3.12,-1.352 -3.12,-3.12s1.352,-3.12 3.12,-3.12h5.72c1.768,0 3.12,1.352 3.12,3.12s-1.352,3.12 -3.12,3.12z" />
        <path
            android:fillColor="#11AEBA"
            android:pathData="M6.968,49.92c-1.04,0 -2.08,-0.52 -2.704,-1.56 -0.832,-1.456 -0.312,-3.432 1.144,-4.264l4.888,-2.808c1.456,-0.832 3.432,-0.312 4.264,1.144 0.832,1.456 0.312,3.432 -1.144,4.264l-4.888,2.808c-0.416,0.312 -0.936,0.416 -1.56,0.416z" />
        <path
            android:fillColor="#3BEDCB"
            android:pathData="M52.52,23.608c-1.04,0 -2.08,-0.52 -2.704,-1.56 -0.832,-1.456 -0.312,-3.432 1.144,-4.264l4.888,-2.808c1.456,-0.832 3.432,-0.312 4.264,1.144 0.832,1.456 0.312,3.432 -1.144,4.264l-4.888,2.808c-0.52,0.312 -1.04,0.416 -1.56,0.416z" />
        <path
            android:fillColor="#0FB8BC"
            android:pathData="M17.68,60.528c-0.52,0 -1.04,-0.104 -1.56,-0.416 -1.456,-0.832 -1.976,-2.808 -1.144,-4.264l2.808,-4.888c0.832,-1.456 2.808,-1.976 4.264,-1.144 1.456,0.832 1.976,2.808 1.144,4.264l-2.808,4.888c-0.624,1.04 -1.664,1.56 -2.704,1.56z" />
        <path
            android:fillColor="#57F7D8"
            android:pathData="M43.992,15.08c-0.52,0 -1.04,-0.104 -1.56,-0.416 -1.456,-0.832 -1.976,-2.808 -1.144,-4.264l2.808,-4.888c0.832,-1.456 2.808,-1.976 4.264,-1.144 1.456,0.832 1.976,2.808 1.144,4.264l-2.808,4.888c-0.624,0.936 -1.664,1.56 -2.704,1.56z" />
    </group>
</vector>

添加动画loading_vector_rotate.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
        android:duration="2000"
        android:interpolator="@android:anim/linear_interpolator"
        android:propertyName="rotation"
        android:repeatCount="-1"
        android:valueFrom="0"
        android:valueTo="720"
        android:valueType="floatType" />
</set>

使用animated-vector添加 loading_vector.xml如下
target里的name 就是我们vector图片里的属性,这里就是我们新加的group的名字,然后animation就是给这个group标签里的属性添加动画,我们这里就加了个旋转动画,还可以有拉伸和平移的动画可以添加

<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/ic_loading_d">
    <target
        android:name="root"
        android:animation="@anim/loading_vector_rotate" />
</animated-vector>

当然了,target还可以添加别的,比如vector里的某个path标签属性,我们可以修改stroke,fillColor,trim属性等等.
这样一个简单的自动旋转的Progressbar的图片就ok了

    <ProgressBar
        android:id="@+id/pb_show"
        android:layout_width="65dp"
        android:layout_height="65dp"
        android:indeterminateDrawable="@drawable/loading_vector"

如下图效果


image.png
  1. 图片缺失一部分
    代码如下
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="45dp"
    android:height="66dp"
    android:viewportWidth="45"
    android:viewportHeight="66">
  <path
      android:pathData="M36.805,8.445C32.89,4.529 28.165,2.57 22.631,2.57c-5.534,0 -10.259,1.958 -14.174,5.874 -3.915,3.915 -5.873,8.64 -5.873,14.174 0,2.845 0.43,5.181 1.292,7.009l14.291,30.306a4.51,4.51 0,0 0,1.821 2.035,5.03 5.03,0 0,0 2.643,0.745 5.03,5.03 0,0 0,2.643 -0.745,4.75 4.75,0 0,0 1.86,-2.035l14.252,-30.306c0.861,-1.828 1.292,-4.164 1.292,-7.01 0,-5.533 -1.957,-10.258 -5.873,-14.173zM29.718,29.705c-1.958,1.958 -4.32,2.937 -7.087,2.937 -2.767,0 -5.13,-0.979 -7.087,-2.936 -1.958,-1.958 -2.937,-4.32 -2.937,-7.087 0,-2.767 0.98,-5.13 2.937,-7.087 1.958,-1.958 4.32,-2.937 7.087,-2.937 2.767,0 5.13,0.979 7.087,2.937 1.957,1.957 2.936,4.32 2.936,7.087 0,2.766 -0.979,5.128 -2.936,7.087z"
      android:fillColor="#FF5D5A"
      android:fillType="nonZero"/>
</vector>

预览图正常


image.png

可实际在app看到的长这样


image.png

使用的地方有两个
ImageView dropPin = new ImageView (getContext());
    dropPin.setImageResource(R.drawable.ic_pin);

还有个是拿到drawable,拿到bitmap,呆会要修改就不帖了
最开始的解决办法:因为app里还有别的颜色的这种图片,长得差不多,不过整体宽高是一样的,就替换成别的图片的pathData了,发现没问题,根源应该还是这图有问题

然后今天突发灵感,想到试下兼容的ImageView,也就是AppCompatImageView,结果真的可行

    ImageView dropPin = new AppCompatImageView(getContext());
    dropPin.setImageResource(R.drawable.ic_pin);

获取bitmap的工具类也改了下
修改了Drawable drawable = context.getDrawable(resId);

    public static Bitmap getDrawableBitmap(final Context context, int resId) {
        final Bitmap bitmap;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//下边这行修改了,使用的是AppCompatImageView里用到的方法
            Drawable drawable = AppCompatResources.getDrawable(context,resId);
            bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
                    drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(bitmap);
            drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
            drawable.draw(canvas);
        } else {
            bitmap = BitmapFactory.decodeResource(context.getResources(), resId);
        }
        return bitmap;
    }

课外知识

咋画一个圆?里用三阶贝塞尔曲线
下边的文章分析了原理,我们用结果就行
https://www.jianshu.com/p/5198d8aa80c1
記住红框里的数字即可。魔法数值0.551915024494 四舍五入我们用0.552就行了。

image.png

下边小圆是ui给的,半圆是我们里用上边的魔法值0.552自己画的

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="45dp"
    android:height="45dp"
    android:viewportWidth="40"
    android:viewportHeight="40">
    <path
        android:pathData="h40,0v0,40,h-40,0v0,40z"
        android:strokeWidth="1"
        android:strokeColor="@color/colorPrimary" />
    <path
        android:fillColor="#C33131"
        android:fillType="evenOdd"
        android:pathData="M24,9.1c-0.5,1.5,0.3,3.1,1.8,3.6c1.5,0.5,3.1-0.3,3.6-1.8c0.5-1.5-0.3-3.1-1.8-3.6C26.1,6.8,24.5,7.6,24,9.1z" />

    <path android:pathData="m10,20c0,5.523,4.477,10,10,10c5.523,0,10,-4.477,10,-10"
        android:fillColor="@color/colorPrimary"
        android:fillType="evenOdd"/>
</vector>

image.png

参考
https://www.jianshu.com/p/9f3221179e3c

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,179评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,229评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,032评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,533评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,531评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,539评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,916评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,813评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,568评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,654评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,354评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,918评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,152评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,852评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,378评论 2 342

推荐阅读更多精彩内容