Android动画——仿vivo指纹动画效果


Google在发布Android 5.0的时候,提供了对Vector的支持,实现了矢量图中Path部分,当然,这不是主要的,主要的是矢量图动画的支持,让我们的app更是充满乐趣!


先上下仿指纹动画的效果图:

Android动画——仿vivo指纹动画效果_第1张图片

从效果图上我们看出,这每一条线都是贝塞尔曲线,由起点,控制点和终点决定着每一条线,对应着矢量图中的path。


1.矢量图xml

看代码片断(在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是本次椭圆绘画的终点坐标(画到这个点结束,并不是把椭圆画完整)。


贝塞尔曲线示例:

Android动画——仿vivo指纹动画效果_第2张图片


有了贝塞尔曲线的所有path,这还不算完,关键是要让它动起来。

2.动画xml

既然要创建动画,我们在res下建立animator文件夹,建一个anim_trim_path_end.xml文件:


这里面有个新的东西trimPathEnd,这个是android矢量图做动画的关键,从0到1,0代表着从空白的开始画path,1即为百分之百的画完了。如果不明白,直接看网上的一个图,一个正方形trimPathEnd从0到1:

Android动画——仿vivo指纹动画效果_第3张图片


当然,对path动画除了这个属性外还有个对应的trimPathStart,这个和trimPathEnd刚好相反,代表着擦除动画,0代表着一画完整的path,0.5表示擦了一半,即只显示path的后半段路径,1表示擦除完全,将会什么也不显示。


有了动画xml之外,还得有一个东西,关连动画xml和矢量图xml。那就是


3.关连xml

在res/drawable中建一个bezier_anim12.xml,对应代码:


    
    
    

name对应着矢量图path中的name,animation对应着动画中的xml,不同的target对应着不同的path。

有了这个xml,我们可以在布局文件里使用它:

    


有了这些,我们便可以在activity里作动画了,通过AnimatedVectorDrawable的start方法,可以让它动起来。

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;
        }
    }
}

这里使用了butterknife插件,可以支持对资源、事件等的绑定,在这里我就不具体讲了,可以百度一下,这个插件可以让我们不用再去什么findViewById,不用去setXXXLestener啥的。


具体代码已上传到github:https://github.com/jxr202/VivoFingerprintAnimator


有兴趣大家一块讨论。


上学的时候,老师曾教导了我一句话,挺深刻的:不积跬步,无以至千里。。。



你可能感兴趣的:(Android动画——仿vivo指纹动画效果)