1. 程式人生 > >簡單實現android炫酷註冊頁面動畫

簡單實現android炫酷註冊頁面動畫

最近比較閒,再加上以前懶惰的習慣,決定儘量保持幾天一篇部落格,這次簡單實現一下這個效果.其實主要是在網上看到了一篇部落格,裡面的效果比較炫,只是我覺得那個之前那個部落格的動畫有些地方的銜接沒有做好,並且沒有真正還原原設計,所以這裡重新寫了一下,簡單的實現.原部落格地址:http://www.jianshu.com/p/3ff40a06bef6,可以看看之前的實現效果以及原設計的效果。
錄製效果有點渣.輕噴!
這裡寫圖片描述
接上個gif圖:
這裡寫圖片描述
接下來就開始一步一步分析吧.
首先就是一個比較簡單過場動畫,具體什麼是過場動畫我就不多說了,不懂的詳細瞭解一下我這裡不講原因,只講講如何實現。這裡有2個activtiy,主要的東西其實都在第二個activity裡.第一個頁面就一個texteview不多說,詳細說說第二個activity吧。

http://androidwing.net/index.php/172 這一篇我覺得很不錯,大家可以看看。
既然是要實現過場動畫,那首先第二個activity就要設定這樣的屬性

<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@android:color/transparent</item>

其中SIGNUP這個TextView是一個共享元素,在2個activity中具有一樣的屬性.在跳轉到第二個activity之前.我們需要穿一些第一個activity中Textview的屬性值過去.如下圖:

public void singUp(View view){

        //獲取view在螢幕中的位置以及寬高做為引數傳到第二個activity
        int[] location = new int[2];
        view.getLocationOnScreen(location);
        Intent intent = new Intent(this, HomeActivity.class);
        intent.putExtra("left", location[0]);
        intent.putExtra("top", location[1
]); intent.putExtra("width", view.getWidth()); intent.putExtra("height", view.getHeight()); startActivity(intent); overridePendingTransition(0, 0); }

記住一點要呼叫overridePendingTransition(0, 0),關閉系統預設的跳轉動畫。
在第二個activity中接受到這些引數.

tv_sign_up.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {

                layout_sign_up.getViewTreeObserver().removeOnGlobalLayoutListener(this);

                startRevel();
            }
        });

由於第二個acitivity中還有個success和一個下劃線line.所以這裡我把他們放在一個佈局裡了.

<RelativeLayout
        android:id="@+id/layout_sign_up"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true">

        <TextView
            android:id="@+id/tv_sign_up"
            android:layout_width="100dp"
            android:layout_height="30dp"
            android:layout_marginBottom="20dp"
            android:gravity="center"
            android:text="@string/sign_up"
            android:textColor="@android:color/white" />

        <TextView
            android:id="@+id/tv_success"
            android:layout_width="100dp"
            android:layout_height="30dp"
            android:layout_marginBottom="20dp"
            android:gravity="center"
            android:text="@string/success"
            android:textColor="@android:color/white"
            android:visibility="invisible" />

        <View
            android:id="@+id/line_view"
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:layout_marginTop="35dp"
            android:background="@android:color/white"
            android:visibility="gone" />
    </RelativeLayout>

好了,寫好了最基本的東西就開始實現動畫了。
第一步,獲取到上一個activity傳過來的引數,然後計算出上一個activity中textview的位置及大小(如果大小不一樣大需要縮放一下)。

//拿到上一個activity中textview的屬性
        Intent intent = getIntent();
        int left = intent.getIntExtra("left", 0);
        int top = intent.getIntExtra("top", 0);
        int width = intent.getIntExtra("width", 0);
        int height =intent.getIntExtra("height", 0);

        //獲取到當前控制元件的屬性
        int[] location = new int[2];
        layout_sign_up.getLocationOnScreen(location);
        int curX = location[0];
        int curY = location[1];
        //計算出差值
        int transX = left - curX;
        int transY = top - curY;
        //把當前的控制元件先移動到上一個activity中textview所處的位置
        layout_sign_up.setX(layout_sign_up.getX() + transX);
        layout_sign_up.setY(layout_sign_up.getY() + transY);

然後就可以實現圓弧的擴散動畫和textview的平移回原位的動畫了.
這裡圓弧的實現我們適用一個第三方的庫,在gradle新增如下依賴:

compile('com.github.ozodrukh:CircularReveal:[email protected]') {
        transitive = true;
    }

具體使用:

        int cx = left + width / 2;
        int cy = top - height / 2;
        float radius = (float) Math.hypot(reveal_layout.getWidth(), reveal_layout.getHeight());
        Animator animator;
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){

            animator = ViewAnimationUtils.createCircularReveal(reveal_layout, cx, cy, 0, radius);
            animator.setDuration(700);
            animator.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationStart(Animator animation) {
                    reveal_layout.setVisibility(View.VISIBLE);
                }
            });
            animator.start();
        }

首先cx,cy是計算出當前矩形的中心點.(從中心點開始擴散),radius是計算出最終擴散的圓弧半徑。由於是整個螢幕所以這裡其實就是勾股定理的公式。
效果如下:
這裡寫圖片描述

ViewAnimationUtils.createCircularReveal(reveal_layout, cx, cy, 0, radius);

這裡的幾個引數其實就很簡單了. 引數的意思依次是要控散的控制元件(不知道描述清楚沒有),擴散中心的x座標,擴散中心的y座標,剛開始擴散的圓弧半徑,最終擴散的圓弧的半徑.(如果不熟悉的可以下載原始碼更改一下引數看看效果就知道了,很簡單的.)這裡平移和擴散動畫是一起執行的,平移動畫如下:

        Point start = new Point(layout_sign_up.getX(), layout_sign_up.getY());
        Point end = new Point(curX, curY - getStatusBarHeight(this));
        ValueAnimator animator1 = ValueAnimator.ofObject(new PointEvaluator(), start, end);
        animator1.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {

                Point curPoint = (Point) animation.getAnimatedValue();

                layout_sign_up.setX(curPoint.getX());
                layout_sign_up.setY(curPoint.getY());
            }
        });
        animator1.setDuration(700);
        animator1.start();

多說一句,這裡我使用view.getLocationOnScreen這個方法,不知道為什麼獲取的位置有誤,沒有算上標題欄.所以導致平移的位置沒有回到中心,所以我減去了標題欄的高度.curY - getStatusBarHeight(this),讓其又往上平移了一段距離。效果如下:
這裡寫圖片描述
組合在一起就是如下效果了:
這裡寫圖片描述
接下來就是實現後面的效果了:文字進入和離開的動畫,以及line線的縮放動畫:

final ObjectAnimator lineAnim = ObjectAnimator.ofFloat(line, "ScaleX", 0f, 0.6f, 0.9f, 1f);
        lineAnim.setDuration(1500);
        lineAnim.setInterpolator(new DecelerateInterpolator());
        line.setPivotX(0);

這裡利用setPivotX(0)方法把線條執行動畫的起始點改為0,動畫將以該座標為中線開始縮放,(預設為view的中線點),這樣擴大動畫只會向一個方向發生,即可實現線條延長效果。動畫播放數值”0, 0.6f, 0.9f, 1.0f”並不是等差排列,還是越來越小,這樣即可實現減速效果。
線條效果如下:可以看到最後一點是以很慢的速度完成的。
這裡寫圖片描述
接下來是文字的進入和離開的動畫了.都是比較簡單的平移和透明度漸變動畫,只不過組合再了一起.

//success進入
    private void successEnter() {

        if(tv_success.getVisibility() != View.VISIBLE){
            tv_success.setVisibility(View.VISIBLE);
        }

        //得到success的寬度,然後設定起始位置以及終點位置
        ObjectAnimator sucessTran = ObjectAnimator.ofFloat(tv_success, "TranslationX", -measuredWidth*1.2f, -measuredWidth*0.2f, 0f);
        //透明度漸變從0-1
        ObjectAnimator sucessAlpha = ObjectAnimator.ofFloat(tv_success, "Alpha", 0.1f, 0.8f, 1f);

        //此處同理
        ObjectAnimator signupTran = ObjectAnimator.ofFloat(tv_sign_up, "TranslationX", 0, measuredWidth*0.7f, measuredWidth* 1.5f);
        signupTran.setInterpolator(new AccelerateInterpolator());
        ObjectAnimator signupAplha = ObjectAnimator.ofFloat(tv_sign_up, "Alpha", 1.0f, 1.0f, 0.4f, 0f);

        AnimatorSet set = new AnimatorSet();
        set.setDuration(1000);
        set.playTogether(sucessTran, sucessAlpha, signupTran, signupAplha);
        set.start();
        set.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                handler.sendEmptyMessageDelayed(0, 800);
            }
        });
    }

 private void singupEnter() {

        ObjectAnimator signupTran = ObjectAnimator.ofFloat(tv_sign_up, "TranslationX", -measuredWidth*1.2f, -measuredWidth*0.2f, 0f);
        ObjectAnimator signupAplha = ObjectAnimator.ofFloat(tv_sign_up, "Alpha", 0.1f, 0.8f, 1f);

        ObjectAnimator successTran = ObjectAnimator.ofFloat(tv_success, "TranslationX", 0, measuredWidth*0.7f, measuredWidth* 1.5f);
        successTran.setInterpolator(new AccelerateInterpolator());
        ObjectAnimator successAlpha = ObjectAnimator.ofFloat(tv_success, "Alpha", 1.0f, 1.0f, 0.4f, 0f);

        AnimatorSet set = new AnimatorSet();
        set.setDuration(1000);
        set.playTogether(signupTran, signupAplha, successTran, successAlpha);
        set.start();
        set.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                handler.sendEmptyMessageDelayed(0, 1000);
            }
        });
    }

上面的2個動畫都是很簡單的動畫,這裡就不多說了.以下是動畫迴圈:

 int index = 0;

    private void loopAnim() {

        if(index % 2 == 0){

            successEnter();
        }else{

            singupEnter();
        }
        index++;
    }

    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            //此處模擬網路請求,5次之後執行最後一個背景收起的動畫
            if(index >= 5){

                enterHome();
            }else {

                loopAnim();
            }
        }
    };

剩下 最後的背景收起動畫我同樣使用了屬性動畫,程式碼如下:

private void enterHome() {

        im.setVisibility(View.VISIBLE);
        rl_title.setVisibility(View.VISIBLE);
        scale_layout.setVisibility(View.VISIBLE);
        reveal_layout.setVisibility(View.GONE);
        layout_sign_up.setVisibility(View.GONE);

        ValueAnimator valueAnimator = ValueAnimator.ofInt(scale_layout.getHeight(), 0);
        valueAnimator.setInterpolator(new DecelerateInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
        {
            @Override
            public void onAnimationUpdate(ValueAnimator animation)
            {
                scale_layout.getLayoutParams().height = (int) animation.getAnimatedValue();
                scale_layout.requestLayout();
            }
        });

        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.playTogether(valueAnimator,
                ObjectAnimator.ofFloat(iv_me, "Alpha", 0.1f, 1.0f),
                ObjectAnimator.ofFloat(iv_menu, "Alpha", 0.1f, 1.0f));
        animatorSet.setDuration(1200);
        animatorSet.start();
    }

在屬性動畫中,我監聽了addUpdateListener,這裡的animation引數可以獲取到當前改變的值:
animation.getAnimatedValue();當然變化的範圍就是從layout的高度減小到0,所以這裡我拿到改變的值,直接設定給layout的佈局引數中的height相當於動態的改編其高度.(這個技巧其實很實用,我寫的第一篇部落格也實用到這個技巧)。最後就是對title的2個view進行透明度的漸變:

其實在平常的看到的很多例子裡,有些看上去很炫的效果其實都是一些比較基本的東西組合起來的.我們平常寫程式碼也是一樣,都是用最基本的東西通過對程式碼不同的組合,以此來實現不同的需求,動畫也是一樣,最重要的就是要分析出來每個動畫都是由什麼方式實現的,最後加以組合。原始碼在這裡:
https://github.com/wxkkwxxx/MyAnim

相關推薦

簡單實現android註冊頁面動畫

最近比較閒,再加上以前懶惰的習慣,決定儘量保持幾天一篇部落格,這次簡單實現一下這個效果.其實主要是在網上看到了一篇部落格,裡面的效果比較炫,只是我覺得那個之前那個部落格的動畫有些地方的銜接沒有做好,並且沒有真正還原原設計,所以這裡重新寫了一下,簡單的實現.原部落

Android的Toolbar+Bottom+Fab懸浮按鈕顯示、隱藏、漸變的各種實現姿勢

前言   由於手機螢幕大小的限制,各種控制元件需要根據需求進行顯示,隱藏,移動等,以增加視覺效果,使用者體驗。就拿目前市場上常見的APP如知乎、QQ、淘寶、美團等來說,在他們的APP裡面隨處可見一些比較優美的處理方案。本文主要將一些常見的需要對控制元件進行顯示

Android 自定義View實現動態按鈕

普通按鈕也就那麼幾種樣式,看著都審美疲勞,先放效果圖,演示Demo+原始碼在最後面 你會不會以為這個按鈕是集結了很多動畫的產物,我告訴你,並沒有。所有的實現都是基於自定義View,採用最底層的onDraw一點一點的畫出來的。沒有采用一丁點的動畫。雖然演示時間很短,但是要

C# Winform實現的透明動畫介面(轉載)

http://www.cnblogs.com/Joetao/articles/4631868.html 做過.NET Winform窗體美化的人應該都很熟悉UpdateLayeredWindow吧,UpdateLayeredWindow可以實現窗體的任意透明,效

簡單實現iframe的高度根據頁面內容自適應(jQuery方式)

eight var 調用 pos jquery 出現 引用 main body 這篇文章主要介紹了簡單實現iframe的高度根據頁面內容自適應(jQuery方式),以及在ie瀏覽器下的相關問題 方式一: //註意:下面的代碼是放在和iframe同一個頁面中調用 $("

安卓音、視頻播放功能簡單實現 --Android基礎

ket undle 顯示 perm err efault 繼續 bre mpat 1、音樂播放功能 關鍵代碼: MainActivity.java: package thonlon.example.cn.musicdemowithoutservice;import

jQuery簡單實現iframe的高度根據頁面內容自適應的方法(轉)

var contents color iframe meid clas 簡單實現 方式 根據 本文實例講述了jQuery簡單實現iframe的高度根據頁面內容自適應的方法。分享給大家供大家參考,具體如下: 方式1: //註意:下面的代碼是放在和iframe同一個

Android廣東快樂十分搭建的播放效果

tar operation container animation text one ESS eal ola 使用廣東快樂十分搭建述 dsluntan.com 貝塞爾曲線實現滑動效果,在使用屬性動畫實現水波紋效果,然後就能實現以上效果 三、實現 1、先封裝動畫框架,創建動

Android 選單

compile 'com.nightonke:boommenu:2.0.3' 選單的位置是可以設定的  , 形狀也可以,背景顏色也可以 這個有N種樣式,可去下載Apk 挑選 MainXML <?xml version="1.0" encoding="utf-

簡單實現Android視訊播放器倍速、清晰度切換、m3u8下載

簡單的前提是使用開源庫 在庫的基礎上新增相對應的功能, 以 JiaoZiVideoPlayer 為例 ,本身自帶的播放引擎是MediaPlayer,也就是Android自帶的播放器,有很多不完善的地方,倍速切換隻支援5.0以上,否則報 NoClassDefFoundError 錯誤

Android 的多重水波紋 MultiWaveHeader

自去年第一次釋出開源庫SmartRefreshLayout以來,深刻的感受到了開源的樂趣。 所以打算以後開發過程中把一些自己實現的實用開源庫也開源出來,供大家使用、討論、升級。 MultiWaveHeader 便是第二個釋出的開源庫!先來看看下面的展示效果吧

Android的UI介面

Android酷炫實用的開源框架(UI框架) 前言 忙碌的工作終於可以停息一段時間了,最近突然有一個想法,就是自己寫一個app,所以找了一些合適開源控制元件,這樣更加省時,再此分享給大家,希望能對大家有幫助,此博文介紹的都是UI上面的框架,接下來會有其他的開源框架(如:HTTP框架、DB框架)。

Android的效果

首先主要介紹幾種常見的產品引導介紹方式。 GuideView GuideView是一個遮罩式的導航頁,能夠快速為任何一個View建立一個遮罩層,支援單個頁面,多個引導提示,支援為高亮區域設定不同的圖形,支援引導動畫,方便擴充套件。 效果圖: ShowcaseView 一個通過區域性高亮達到突出重點,實現

簡單實現Android頂部工具欄和底部工具欄

直接上圖,有圖有真相。 這兩個工具欄全是用佈局來實現的。 底部工具欄佈局程式碼: <?xml version="1.0" encoding="utf-8"?><RelativeLayout     ="http://schemas.androi

簡單實現Android圖片三級快取機制

    使用者在使用我們的APP時,通常會重複瀏覽一些圖片,這時如果每一次瀏覽都需要通過網路獲取圖片,那麼將會非常流量。為了節省使用者流量,提高圖片載入效率,我們通常使用圖片三級快取策略,即通過網路、本地、記憶體三級快取圖片,來減少不必要的網路互動,避免浪費流量

【Transition】Android的Activity切換效果,共享元素

本文原專案地址為:https://github.com/lgvalle/Material-Animations 在文章最後,有我自己對著這個專案手敲的一份。 程式碼基本一模一樣,只有略微的修改,加了一些註釋,以及將其中大多數英文翻譯成了中文。 此篇 API 均為 Andro

Android的天氣動畫控制元件

今日推薦WeatherView是一個Android庫,可以幫助你做一個很酷的天氣動畫為您的應用程式。 這個圖書館是基於這個Leonids圖書館。 使用Android Studio / grandle 新增到專案的build.gradle裡面 :

簡單實現Android搜尋功能 顯示清除歷史搜尋記錄

本文主要為大家分享了Android實現搜尋功能,並且可以實時顯示搜尋的歷史記錄,根據輸入的內容去模糊查詢,供大家參考,介面圖如下。 本案例實現起來也非常的簡單,所以可以直接拿來嵌入專案中使用,主要涉及到的知識點: 1、資料庫的增刪改查操作 2、監聽軟鍵盤迴車按鈕設

Android 外掛

做專案有的時候需要用到一些特殊效果,自己重定義,重寫太麻煩,優化也不好。 放出幾個網址,裡面各種動畫效果和特殊用法。 http://www.23code.com/sensey/ http://blog.csdn.net/easyer2012/article/details

WebView詳解與簡單實現Android與H5互調

本篇文章已授權微信公眾號 guolin_blog (郭霖)獨家釋出 為什麼要學習Android與H5互調? 微信,QQ空間等大量軟體都內嵌了H5,不得不說是一種趨勢。Android與H5互調可以讓我們的實現混合開發,至於混合開發就是在一個App中內嵌