1. 程式人生 > >Android 指紋掃描動畫實現,仿新版360手機助手歡迎頁

Android 指紋掃描動畫實現,仿新版360手機助手歡迎頁

轉載請標明出處: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;
    }

到這裡整個動畫都基本介紹完了,大家對於文章內容有興趣的話,歡迎多多交流,下載原始碼,請點選這裡