Android 指纹扫描动画实现,仿新版360手机助手欢迎页

来源:互联网 发布:算法时代 下载 编辑:程序博客网 时间:2024/04/29 22:41

转载请标明出处:http://blog.csdn.net/edisonchang/article/details/49914553
最近看到360手机助手改版了,自己也装了一个,整体的体验还是比较不错,在新版的用户引导页有一个指纹的扫描动画,扫描时候会有一个类似水波纹扩散的效果,感兴趣的朋友可以点链接下载看看。博主最近做的需求刚好和这个效果比较类似,借着这个机会自己实现了一个demo,

指纹扫描动画
下面简单介绍下一些技术要点和实现方法。

提到Android的动效,还是有一些知识点要注意的。首先来了解下Android关于动画的一些基本概况,Android 提供三种动画类型:View 动画、帧动画和属性动画。View 动画通过对视图的简单缩放、平移、旋转、改变透明度等(或者组合方式)从而产生动画效果,帧动画也算是一类比较特殊的View动画,相比View动画的展现形式略为不同,类似gif动画图,理解起来也比较容易,此处就不再展开。

虽然View动画支持自定义,但还是存在一些局限性。比如在某些场景下,我们希望View 动画停止后的位置就是最终位置,诸如此类效果,View 动画是做不到的。这也是属性动画产生的原因,因为属性动画是通过动态的改变对象的属性从而达到动画效果,是Api 11 后的新特性,在之前的版本的平台上虽然可以用开源动画库nineoldandroids 进行兼容,但动画的本质依旧是View动画,这一点可以通过阅读nineoldandroids的源码了解。

所以在android3.0以前的系统上,不管用View动画还是用属性动画,动画结束后,View的位置依然没有变化,这一点在我们处理单击事件时尤其关键,博主也曾经遇到过处理这类点击事件兼容问题,如果有朋友对此比较感兴趣,我可以写一篇文章介绍下。

深入的了解各种动画的特点和使用场景,有利于我们在实际开发中能够选择更好的动画方案。就以拿本例来说,动画效果由两部分组成,第一部分是指纹扫描动画,第二部分是触摸屏幕后的水波纹扩散动画。博主针对两种动画类型分别采用View动画和属性动画来实现。

(1)指纹扫描动画,这算是一个比较典型的View动画,实现动画要做的就是对动画过程的剖解。从最终效果来看:有一条红色扫描线在一个圆形的指纹窗口竖直循环滚动,所以本质上就是一个View的循环平移动画。整体的视图可以分为三层构成,layout 布局如下:

   <FrameLayout        android:id="@+id/user_scan"        android:layout_width="match_parent"        android:layout_height="match_parent">        <ImageView            android:id="@+id/user_scan_1"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_gravity="center"            android:scaleType="fitXY"            android:src="@drawable/scan_1" />        <ImageView            android:id="@+id/user_scan_2"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_gravity="center"            android:scaleType="fitXY"            android:src="@drawable/scan_2" />        <RelativeLayout            android:layout_width="match_parent"            android:layout_height="match_parent">            <ImageView                android:id="@+id/user_scan_3"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:layout_centerInParent="true"                android:scaleType="fitXY"                android:src="@drawable/scan_3" />            <TextView                android:id="@+id/user_scan_text"                android:layout_width="match_parent"                android:layout_height="match_parent"                android:layout_below="@+id/user_scan_3"                android:background="@android:color/white"                android:gravity="center_horizontal"                android:text="@string/long_press_scan"                android:textColor="#8d8d8d"                android:textSize="18dp" />        </RelativeLayout>    </FrameLayout>

最底层scan_1为指纹图,scan_2是红线,scan_3 是一个中间镂空的圆形图片。动画的产生过程,其实就是View scan_2的translateAnimation 动画,因为View scan_2 Z方向上层还有镂空圆形图片,所以从动画实现效果看红线的横向长度也伴随着上下平移而产生变化,代码如下:

    private void playScanAnimation() {        ImageView imageLine = (ImageView) layoutScan.findViewById(R.id.user_scan_2);        scanTranslateAnimation = new TranslateAnimation(0.0f, 0.0f, 10.0f, DensityUtils.dp2px(getApplicationContext(), 110));        scanTranslateAnimation.setDuration(3000);        scanTranslateAnimation.setRepeatMode(Animation.RESTART);        scanTranslateAnimation.setRepeatCount(Animation.INFINITE);        imageLine.setAnimation(scanTranslateAnimation);        scanTranslateAnimation.startNow();    }

TranslateAnimation 定义动画开始和结束的相对位置,setRepeatMode 设为 Animation.RESTART,表示指纹的扫描每次都是正方向的从上到下轮播。怎么样,实现起来是不是很简单,这一类动画也可以通过属性动画的translationY属性来实现,当然动画效果是一样的,有兴趣的朋友可以自行尝试。

(2)触摸屏幕后的水波纹展开动画。动画过程存在两个阶段,第一个阶段是中间圆形区域的指纹背景,从白色到红色的渐变动画,第二个阶段是波动动画的循环扩散,所以我们应该在第一个阶段动画结束后马上开始第二阶段的动画,保证动画整体的连贯性。以下是动画视图的布局文件,由两层组成,下面一层为波纹动画,上面一层为指纹图像。

    <FrameLayout        android:id="@+id/user_find"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:visibility="gone">        <ImageView            android:id="@+id/user_find_wave"            android:layout_width="match_parent"            android:layout_height="match_parent"            android:layout_gravity="center" />        <ImageView            android:id="@+id/user_find_1"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_gravity="center"            android:scaleType="fitXY"            android:src="@drawable/pressed" />    </FrameLayout>

第一阶段的动画,依然可以采用View 动画方式实现,而波纹圆圈imageViewWave 的半径radius从小到大变化时,圆圈的stoke width 是从大到小, 这些特征都是View 的属性参数,所以我们采取属性动画。

   private void playFindAnimation() {        ImageView imageViewFind = (ImageView) layoutFind.findViewById(R.id.user_find_1);        final ImageView imageViewWave = (ImageView) layoutFind.findViewById(R.id.user_find_wave);        if (waveDrawble == null) {            waveDrawble = new WaveDrawable(this, Color.parseColor("#ff6262"), DensityUtils.dp2px(getApplicationContext(), 40));        }        waveDrawble.setInterpolator(new LinearInterpolator());        waveDrawble.setRepeatCount(Animation.INFINITE);        waveDrawble.setWaveAnimatorListener(new WaveDrawable.WaveAnimatorListener() {            @Override            public void onAnimationEnd() {            }        });        imageViewWave.setImageDrawable(waveDrawble);        imageViewWave.setVisibility(View.GONE);        AlphaAnimation alphaAnimation = new AlphaAnimation(0.1f, 1.0f);        alphaAnimation.setDuration(500);        imageViewFind.setAnimation(alphaAnimation);        alphaAnimation.setAnimationListener(new Animation.AnimationListener() {            @Override            public void onAnimationStart(Animation animation) {            }            @Override            public void onAnimationEnd(Animation animation) {                imageViewWave.setVisibility(View.VISIBLE);                waveDrawble.startAnimation();            }            @Override            public void onAnimationRepeat(Animation animation) {            }        });        alphaAnimation.startNow();    }

当指纹渐变动画结束时就会回调onAnimationEnd方法开始波纹的扩散动画。 扩散动画是个动画集animatorSet,可以用playTogether 同时进行waveScale、waveStrokeWidth多项的属性动画,主要代码如下:

    private Animator generateAnimation() {        ObjectAnimator waveAnimator = ObjectAnimator.ofFloat(this, "waveScale", 1f, 3f);        waveAnimator.setDuration(animationTime);        if (interpolator != null) {            waveAnimator.setInterpolator(interpolator);        }        waveAnimator.setRepeatCount(repeatCount);        waveAnimator.setRepeatMode(Animation.INFINITE);        ObjectAnimator strokeAnimator = ObjectAnimator.ofFloat(this, "waveStrokeWidth", strokeSize, 0f);        strokeAnimator.setDuration(animationTime);        if (interpolator != null) {            strokeAnimator.setInterpolator(interpolator);        }        strokeAnimator.setRepeatCount(repeatCount);        strokeAnimator.setRepeatMode(Animation.INFINITE);        animatorSet.addListener(new Animator.AnimatorListener() {            @Override            public void onAnimationStart(Animator animator) {            }            @Override            public void onAnimationEnd(Animator animator) {                if (waveAnimatorListener != null){                    waveAnimatorListener.onAnimationEnd();                }            }            @Override            public void onAnimationCancel(Animator animator) {            }            @Override            public void onAnimationRepeat(Animator animator) {            }        });        animatorSet.playTogether(waveAnimator, strokeAnimator);        return animatorSet;    }

到这里整个动画都基本介绍完了,大家对于文章内容有兴趣的话,欢迎多多交流,下载源码,请点击这里

0 0
原创粉丝点击