刚出来的时候好像用vector图片还得gradle配置,代码里配置,现在好像都不需要了,直接可以用了,简单复习下
必须
app的build.gradle里还是得加上这个
不加的话虽然vector图片可以识别,可是发现会模糊
defaultConfig{
//...
vectorDrawables.useSupportLibrary=true
}
- 导入图片
系统提供了一些默认的,也可以用自己写的svg文件
然后看到下图,有两种,
默认系统的,点击红框的部分可以选择别的图片,点击local file就可以选择本地的svg图片,系统会自动转换的,完事next就ok
之后在drawable下就看到对应的xml文件
你不想用系统的,也不想导入svg文件,也可以自己新建一个,自己修改xml文件
- 简单分析下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>
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'处理时,只是移动了画笔, 没有画任何东西。 它也可以在后面给出上同时绘制不连续线。
- 看另外一个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>
这个viewoportWidth和width不一样,也就是24dp被分成了12份,而下边的path,数字大小也是对应这个12份的了,
也就是x12就是最右边,y12就是最下边了。
- 其他的属性
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"/>
- 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"
如下,正常这样的
设置了android:strokeMiterLimit="1"以后这样了,当然了,如果这个值很大,超出了默认的尖角范围的话,那没啥作用了,只有弄个小的值,才能裁掉多余的尖角,额,这个值好像最小值是1?
- name
还都可以起个名字,动画的时候可以根据名字处理path下的某个属性
android:name="xxx"
- 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"/>
然后,我们加上trim属性,效果图就变了,很小的一段了,从圆弧的(0.3+0.2)开始,到(0.3+0.5)结束,我背景画了条绿色的半圆作为参考
android:trimPathStart="0.2"
android:trimPathEnd="0.5"
android:trimPathOffset="0.3"
trim的作用比较大了,动画的时候动态修改这个,就可以显示隐藏path了,也可以动态的一点一点的显示出来.
注意
这里的trimPath 是有限制的,它只作用于path的第一段,如果pathData里有断开的多个path的话,那么是按第一段来算的。
如下图,trimPathEnd是0.5结果就是第一段的一半
代码也很简单,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>
使用中的问题
- 无法获取bitmap
下边这种获取到的bitmap是null
6.0如果有fillType的话,能获取到,其他版本获取不到
Bitmap bitmap= BitmapFactory.decodeResource(getResources(),R.drawable.ic_vector_pic);
解决办法:
① 换回png图片
②通过canvas画出来,后边有提供方法
- 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"
如下图效果
- 图片缺失一部分
代码如下
<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>
预览图正常
可实际在app看到的长这样
使用的地方有两个
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就行了。
下边小圆是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>
参考
https://www.jianshu.com/p/9f3221179e3c