Android應用系列:仿MIUI的Toast動畫效果實現(有圖有源碼)

前言html

  相信有些人用過MIUI,會發現小米的Toast跟Android傳統的Toast特麼是不同的,他會從底部向上飛入,而後漸變消失。看起來效果是挺不錯的,可是對於Android原生Toast是不支持自定義動畫的。那這個效果究竟是怎麼實現的呢?下面就來告訴你。。。。android

分析ide

  若是園友看過個人另外一篇博客《Android:剖析源碼,爲所欲爲控制Toast顯示》,就會知道其實原生Toast就是infate出一個View實例,而後將其加載到WindowManager上面來達到顯示效果。咱們不少人都知道WindowManager是能夠實現一個懸浮在全部應用界面的視圖而不會獲取焦點,這也就是Toast所須要具有的核心的功能:簡約提示信息傳遞給用戶,而不額外執行其餘操做;在這裏,咱們這個效果也是基於WindowManager來實現的。函數

正文佈局

  咱們須要自定義一個Toast的類,可是不須要繼承Toast。既然是仿照着寫一個自定義Toast,那麼咱們就從Toast的入口開始完善這個自定義Toast。post

新建一個類動畫

public class MiuiToast {

}

乾乾淨淨的不用去繼承其餘類(除了Object.......)ui

開始碼代碼this

咱們通常使用原生Toast都是直接 Toast.makeText(this, text, Toast.LENGTH_SHORT).show(); 其中makeText這個靜態方法會返回一個Toast實例,而後調用show方法來顯示Toast。spa

咱們先來搞定makeText方法

public static MiuiToast MakeText(Context context, String text, boolean showTime) {
    MiuiToast result = new MiuiToast(context, text, showTime);
    return result;
}

邏輯簡單粗暴,直接調用構造函數實例化一個MiuiToast對象並返回。

接下來該是MiuiToast的構造方法了

private MiuiToast(Context context, String text, boolean showTime ){
    mShowTime = showTime;//記錄Toast的顯示長短類型
    mIsShow = false;//記錄當前Toast的內容是否已經在顯示
    mWdm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    //經過Toast實例獲取當前android系統的默認Toast的View佈局
    mToastView = Toast.makeText(context, text, Toast.LENGTH_SHORT).getView();
    mTimer = new Timer();
    //設置佈局參數
    setParams();
}

在構造方法中,更多的是對數據的初始化,因爲設置佈局參數比較多,因此單獨抽出一個函數來

瞧瞧setParams()方法

private void setParams() {
    mParams = new WindowManager.LayoutParams();
    mParams.height = WindowManager.LayoutParams.WRAP_CONTENT;  
    mParams.width = WindowManager.LayoutParams.WRAP_CONTENT;  
    mParams.format = PixelFormat.TRANSLUCENT;  
    mParams.windowAnimations = R.style.anim_view;//設置進入退出動畫效果
    mParams.type = WindowManager.LayoutParams.TYPE_TOAST;  
    mParams.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON  
            | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE  
            | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
    mParams.gravity = Gravity.CENTER_HORIZONTAL;
    mParams.y = 250;
}

這個設置參數更可能是參考源代碼中原生Toast的設置參數的類型,在這裏咱們須要注意的是 mParams.windowAnimations = R.style.anim_view;//設置進入退出動畫效果,這個使咱們這個仿MIUI的Toast動畫實現的基石。其餘參數也沒什麼好講的,谷歌就是這麼設置他們的Toast的哈,接下來咱們得看看動畫的配置XML。

這個R.style.anim_view的狀況呢

<resources>
    <style name="anim_view">
        <item name="@android:windowEnterAnimation">@anim/anim_in</item>
        <item name="@android:windowExitAnimation">@anim/anim_out</item>
    </style>
</resources>

這裏定義了一個進入動畫和退出動畫的引用,接下來就是咱們設置動畫效果的時刻了!

anim_in:Toast的進入動畫

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:fromXDelta="0"
        android:fromYDelta="0"
        android:toXDelta="0"
        android:toYDelta="85"
        android:duration="1"
        />
    <translate
        android:fromXDelta="0"
        android:fromYDelta="0"
        android:toXDelta="0"
        android:toYDelta="-105"
        android:duration="350"
        android:fillAfter="true"
        android:interpolator="@android:anim/decelerate_interpolator"
        />
    <alpha 
        android:fromAlpha="0"
        android:toAlpha="1"
        android:duration="100"
        />
    <translate
        android:fromXDelta="0"
        android:fromYDelta="0"
        android:toXDelta="0"
        android:toYDelta="20"
        android:duration="80"
        android:fillAfter="true"
        android:startOffset="350"
        />
</set>

在這裏我配置了四個動畫效果,若是你們要從新設置新的動畫效果,盡能夠在這裏面修改哈。粗略的說幾句,因爲在加載動畫的先後,WindowManager就經過mParams來肯定Toast的顯示位置,因此第一個translate做用是讓Toast在開始載入的時候跳轉到進入的位置,而其餘的動畫就是完成Toast從下端飛入的效果而已,這期間利用了android:startOffset進行時間的控制達到動畫的銜接效果。

anim_out:Toast退出動畫

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <alpha 
        android:fromAlpha="1"
        android:toAlpha="0"
        android:duration="800"/>
</set>

簡簡單單的一個淡出動畫。。。。

而後咱們來看下show()方法吧

public void show(){
    if(!mIsShow){//若是Toast沒有顯示,則開始加載顯示
        mIsShow = true;
        mWdm.addView(mToastView, mParams);//將其加載到windowManager上
        mTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                mWdm.removeView(mToastView);
                mIsShow = false;
            }
        }, (long)(mShowTime ? 3500 : 2000));
    }
}

在show方法中咱們會對mIsShow 判斷當前的Toast是否已經在顯示,若是正在顯示咱們沒理由相信咱們會那麼SB得再去顯示他一次。。

mWdm.addView(mToastView, mParams);將View加載到WindowManager上面,達到相似的懸浮效果,啓動定時器,到達指定的時間後將其移除,整個邏輯就是這樣了。

由於——Toast!就是這麼簡單!

 

給你們瞄瞄效果圖

源碼請戳這裏(點我吧

 

 

做者:enjoy風鈴
出處:http://www.cnblogs.com/net168/
本文版權歸做者和博客園共有,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接,不然下次不給你轉載了。

相關文章
相關標籤/搜索