Google在发布Android 5.0的时候,提供了对Vector的支持,实现了矢量图中Path部分,当然,这不是主要的,主要的是矢量图动画的支持,让我们的app更是充满乐趣!
先上下仿指纹动画的效果图:
从效果图上我们看出,这每一条线都是贝塞尔曲线,由起点,控制点和终点决定着每一条线,对应着矢量图中的path。
看代码片断(在drawable中建一个bezier_svg.xml文件):
解析:
pathData由一串字母组成,有大小写区别,大写是基于原点坐标的位置,小写是基于当前坐标每户的位置。
M(250,155):相当于path中的moveTo方法,将画笔移动到对应的坐标。
C(255,171 || 260,204 || 247,234)(竖线是特意加进去以便观察):这里面有三个坐标,对应着三次贝塞尔曲线的控制点1,控制点2,终点。对贝塞尔曲线有疑问的可以百度。
另外,还有其他的字母,但这里没用到,也一并解析一下:
Q(x, y z, w):对应着二次贝塞尔曲线的控制点(x,y)、终点(z,w)。
L(x,y):以x,y点为终点画一条直线
A(rx,ry,rotation,large_arc_flag,sweep_flag,x,y):这里面参数较多,对应着一个椭圆的各个参数,rx ry为x和y轴的半径,rotation为x轴的旋转角度,两个flat对应的是弧度和绘画方向,最后的x,y是本次椭圆绘画的终点坐标(画到这个点结束,并不是把椭圆画完整)。
贝塞尔曲线示例:
有了贝塞尔曲线的所有path,这还不算完,关键是要让它动起来。
既然要创建动画,我们在res下建立animator文件夹,建一个anim_trim_path_end.xml文件:
当然,对path动画除了这个属性外还有个对应的trimPathStart,这个和trimPathEnd刚好相反,代表着擦除动画,0代表着一画完整的path,0.5表示擦了一半,即只显示path的后半段路径,1表示擦除完全,将会什么也不显示。
有了动画xml之外,还得有一个东西,关连动画xml和矢量图xml。那就是
在res/drawable中建一个bezier_anim12.xml,对应代码:
有了这个xml,我们可以在布局文件里使用它:
Activity代码:
public class MainActivity extends AppCompatActivity {
public @BindView(R.id.bezier) ImageView bezier;
public @BindView(R.id.text) TextView text;
public int stage = 1;
public HashMap vectorDrawableHashMap = new HashMap<>();
public AnimatedVectorDrawable bezierAnimator;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
initVectorDrawable();
}
public void initVectorDrawable() {
text.setText(String.valueOf(stage));
vectorDrawableHashMap.put(1, (AnimatedVectorDrawable) getResources().getDrawable(R.drawable.bezier_anim01, null));
vectorDrawableHashMap.put(2, (AnimatedVectorDrawable) getResources().getDrawable(R.drawable.bezier_anim02, null));
vectorDrawableHashMap.put(3, (AnimatedVectorDrawable) getResources().getDrawable(R.drawable.bezier_anim03, null));
vectorDrawableHashMap.put(4, (AnimatedVectorDrawable) getResources().getDrawable(R.drawable.bezier_anim04, null));
vectorDrawableHashMap.put(5, (AnimatedVectorDrawable) getResources().getDrawable(R.drawable.bezier_anim05, null));
vectorDrawableHashMap.put(6, (AnimatedVectorDrawable) getResources().getDrawable(R.drawable.bezier_anim06, null));
vectorDrawableHashMap.put(7, (AnimatedVectorDrawable) getResources().getDrawable(R.drawable.bezier_anim07, null));
vectorDrawableHashMap.put(8, (AnimatedVectorDrawable) getResources().getDrawable(R.drawable.bezier_anim08, null));
vectorDrawableHashMap.put(9, (AnimatedVectorDrawable) getResources().getDrawable(R.drawable.bezier_anim09, null));
vectorDrawableHashMap.put(10, (AnimatedVectorDrawable) getResources().getDrawable(R.drawable.bezier_anim10, null));
vectorDrawableHashMap.put(11, (AnimatedVectorDrawable) getResources().getDrawable(R.drawable.bezier_anim11, null));
vectorDrawableHashMap.put(12, (AnimatedVectorDrawable) getResources().getDrawable(R.drawable.bezier_anim12, null));
}
private void drawFingerprint() {
if (bezierAnimator != null && bezierAnimator.isRunning()) {
return;
}
text.setText(String.valueOf(stage));
bezierAnimator = vectorDrawableHashMap.get(stage);
bezier.setImageDrawable(bezierAnimator);
bezierAnimator.start();
stage++;
if (stage > 12) {
stage = 1;
}
}
@OnClick({R.id.bezier, R.id.text})
public void onClick(View view) {
switch (view.getId()) {
case R.id.bezier:
drawFingerprint();
break;
case R.id.text:
drawFingerprint();
break;
}
}
}
具体代码已上传到github:https://github.com/jxr202/VivoFingerprintAnimator
有兴趣大家一块讨论。
上学的时候,老师曾教导了我一句话,挺深刻的:不积跬步,无以至千里。。。