Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android從源碼解析並實現各種Toast效果合集

android從源碼解析並實現各種Toast效果合集

編輯:關於Android編程

前言

安卓中為了給用戶的友好提示,一般的表現形式為Dialog、PopWindow、Toast,自從Snackbar的出現絕對是秒殺Toast了,Snackbar不僅能夠簡單實現toast的效果而且還能setAction,但是還是有很多的應用是使用了Toast的,並且安卓死丟丟也有toast的插件,可見toast還是有他存在的價值。

看效果

csdn傳圖片不能太大,馬蛋來2張好了:
這裡寫圖片描述
這裡寫圖片描述

從源碼解讀安卓的Toast

Toast窗口其實和前面分析的Activity、Dialog、PopWindow都是不同的,因為它和輸入法、牆紙類似,都是系統窗口。
我們先看下Toast的靜態makeText方法吧,如下:

public static Toast makeText(Context context, CharSequence text, @Duration int duration) {
        //new一個Toast對象
        Toast result = new Toast(context);
        //獲取前面有篇文章分析的LayoutInflater
        LayoutInflater inflate = (LayoutInflater)   context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        //加載解析Toast的布局,實質transient_notification.xml是一個LinearLayout中套了一個@android:id/message的TextView而已
        View v = inflate.inflate(com.android.internal.R.layout.transient_notification, null);
        //取出布局中的TextView
        TextView tv = (TextView)v.findViewById(com.android.internal.R.id.message);
        //把我們的文字設置到TextView上
        tv.setText(text);
        //設置一些屬性
        result.mNextView = v;
        result.mDuration = duration;
        //返回新建的Toast
        return result;
    }

可以看見,這個方法構造了一個Toast,然後把要顯示的文本放到這個View的TextView中,然後初始化相關屬性後返回這個新的Toast對象。

當我們有了這個Toast對象之後,可以通過show方法來顯示出來,如下看下show方法源碼:

    public void show() {
        ......
        //通過AIDL(Binder)通信拿到NotificationManagerService的服務訪問接口,當前Toast類相當於上面例子的客戶端!!!相當重要!!!
        INotificationManager service = getService();
        String pkg = mContext.getOpPackageName();
        TN tn = mTN;
        tn.mNextView = mNextView;

        try {
            //把TN對象和一些參數傳遞到遠程NotificationManagerService中去
            service.enqueueToast(pkg, tn, mDuration);
        } catch (RemoteException e) {
            // Empty
        }
    }

繼續來看Toast中的show方法的service.enqueueToast(pkg, tn, mDuration);語句,service實質是遠程的NotificationManagerService,所以enqueueToast方法就是 NotificationManagerService類的,如下:

 private final IBinder mService = new INotificationManager.Stub() {
        @Override
        public void enqueueToast(String pkg, ITransientNotification callback, int duration)
        {
            ......
            synchronized (mToastQueue) {
                int callingPid = Binder.getCallingPid();
                long callingId = Binder.clearCallingIdentity();
                try {
                    ToastRecord record;
                    //查看該Toast是否已經在隊列當中
                    int index = indexOfToastLocked(pkg, callback);
                    // If it's already in the queue, we update it in place, we don't
                    // move it to the end of the queue.
                    //注釋說了,已經存在則直接取出update
                    if (index >= 0) {
                        record = mToastQueue.get(index);
                        record.update(duration);
                    } else {
                        // Limit the number of toasts that any given package except the android
                        // package can enqueue.  Prevents DOS attacks and deals with leaks.
                        ......
                        //將Toast封裝成ToastRecord對象,放入mToastQueue中
                        record = new ToastRecord(callingPid, pkg, callback, duration);
                        //把他添加到ToastQueue隊列中
                        mToastQueue.add(record);
                        index = mToastQueue.size() - 1;
                        //將當前Toast所在的進程設置為前台進程
keepProcessAliveLocked(callingPid);
                    }
                    //如果index為0,說明當前入隊的Toast在隊頭,需要調用showNextToastLocked方法直接顯示
                    if (index == 0) {
                        showNextToastLocked();
                    }
                } finally {
                    Binder.restoreCallingIdentity(callingId);
                }
            }
        }
   }

不多看了,我們知道Toast都是加入到一個enqueueToast,然後通過handle來處理,因為是系統的窗口,所以我們換個界面然後toast還沒有完你也不要感到奇怪。

在開發應用程序時使用Toast注意事項:

通過分析TN類的handler可以發現,如果想在非UI線程使用Toast需要自行聲明Looper,否則運行會拋出Looper相關的異常;UI線程不需要,因為系統已經幫忙聲明。 在使用Toast時context參數盡量使用getApplicationContext(),可以有效的防止靜態引用導致的內存洩漏。 有時候我們會發現Toast彈出過多就會延遲顯示,因為上面源碼分析可以看見Toast.makeText是一個靜態工廠方法,每次調用這 個方法都會產生一個新的Toast對象,當我們在這個新new的對象上調用show方法就會使這個對象加入到 NotificationManagerService管理的mToastQueue消息顯示隊列裡排隊等候顯示;所以如果我們不每次都產生一個新的 Toast對象(使用單例來處理)就不需要排隊,也就能及時更新了。

自定義Toast

package com.losileeya.toastmaster.view;

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Handler;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.TranslateAnimation;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;
import android.widget.Toast;

import com.losileeya.toastmaster.R;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Date;

/**
 * 超級自定義的Toast,單例模式獲取本類 
 */
public class SuperCustomToast {
    /**
     * 獲取當前Android系統版本
     */
    static int currentapiVersion = Build.VERSION.SDK_INT;

    /**
     * 入場動畫持續時間
     */
    private static final int TIME_START_ANIM = 500;
    /**
     * 離場動畫持續時間
     */
    private static final int TIME_END_ANIM = 500;
    /**
     * 每條Toast顯示持續時間
     */
    private static final int TIME_DURATION = 2500;
    /**
     * UI線程句柄
     */
    Handler mHandler;

    /**
     * 內容對象
     */
    Context mContext;

    /**
     * 頂層布局
     */
    LinearLayout mTopView, mTopView2;

    /**
     * 內容布局
     */
    public LinearLayout mView;

    /**
     * 布局屬性
     */
    LayoutParams lp_WW, lp_MM;

    /**
     * 屏幕寬度
     */
    int screenWidth;
    /**
     * 屏幕高度
     */
    int screenHeight;

    /**
     * 默認背景的resid
     */
    Integer defaultBackgroundResid;

    /**
     * 默認背景的顏色
     */
    Drawable defaultBackgroundColor;

    /**
     * 默認文字顏色
     */
    int defaultTextColor;
    private View layout;
    /**
     * 反射過程中是否出現異常的標志
     */
    boolean hasReflectException = false;

    /**
     * 單例
     */
    private static SuperCustomToast instance;

    /**
     * 獲得單例
     * 
     * @param context
     * @return
     */
    public static SuperCustomToast getInstance(Context context) {
        if (instance == null) {
            instance = new SuperCustomToast(context);
        }
        return instance;
    }

    private SuperCustomToast(Context context) {
        if (context == null || context.getApplicationContext() == null) {
            throw new NullPointerException("context can't be null");
        }
        mContext = context.getApplicationContext();
        initView();
        initTN();

        // 防反射獲取實例
        if (instance != null)
            throw new NullPointerException("error");
    }

    /**
     * 初始化視圖控件
     */
    public void initView() {
        mHandler = new Handler(mContext.getMainLooper());

        lp_WW = new LayoutParams(LayoutParams.WRAP_CONTENT,
                LayoutParams.WRAP_CONTENT);
        lp_MM = new LayoutParams(LayoutParams.MATCH_PARENT,
                LayoutParams.MATCH_PARENT);
         //獲取屏幕密度
        DisplayMetrics mDisplayMetrics = mContext.getResources()
                .getDisplayMetrics();
                //獲取屏幕寬高
        screenWidth = mDisplayMetrics.widthPixels;
        screenHeight = mDisplayMetrics.heightPixels;

        mTopView = new LinearLayout(mContext);
        mTopView.setLayoutParams(lp_MM);
        mTopView.setOrientation(LinearLayout.VERTICAL);
        mTopView.setGravity(Gravity.CENTER);

        mTopView2 = new LinearLayout(mContext);
        LayoutParams params = new LayoutParams(screenWidth, screenHeight);
        mTopView2.setLayoutParams(params);
        mTopView2.setOrientation(LinearLayout.VERTICAL);
        mTopView2.setGravity(Gravity.BOTTOM);

        mView = new LinearLayout(mContext);
        mView.setLayoutParams(lp_MM);
        mView.setOrientation(LinearLayout.VERTICAL);
        mView.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);

        View gapView = new View(mContext);
        gapView.setLayoutParams(new LayoutParams(screenWidth, screenHeight / 4));
        mView.addView(gapView);

        mTopView.addView(mTopView2);
        mTopView2.addView(mView);

        resetDefaultBackgroundAndTextColor();
    }

    /**
     * 顯示一條Toast
     * layoutId 自定義布局
     * @param msg
     *            消息內容
     */
    public void show(String msg, int layoutId, int rootId, Activity activity) {
        LayoutInflater inflater = activity.getLayoutInflater();
        layout = inflater.inflate(layoutId,
                (ViewGroup) activity.findViewById(rootId));
        layout.setLayoutParams(lp_WW);
        TextView title = (TextView) layout.findViewById(R.id.title);
        title.setText(msg);
        title.setTextColor(defaultTextColor);
        show(layout, null, null, null);
    }

    /**
     * 顯示一條Toast
     * 
     * @param msg
     *            消息內容
     */
    public void show(String msg) {
        show(getTextView(msg), null, null, null);
    }

    /**
     * 顯示一條Toast
     * 
     * @param v
     *            消息內容
     */
    public void show(View v) {
        show(v, null, null, null);
    }

    /**
     * 顯示一條Toast
     * 
     * @param msg
     *            消息內容
     * @param duration
     *            持續時間,單位為毫秒
     */
    public void show(String msg, long duration) {
        show(getTextView(msg), duration, null, null);
    }

    /**
     * 一個toast已經顯示,在下一個msg相同的情況下, 一定時間不顯示新的toast. 如果同樣的消息,在兩次顯示時間差
     * 大於duration的情況下,才出現新的toast
     * 
     * @param msg
     *            消息內容
     * @param duration
     *            持續時間,單位為毫秒
     */
    Long totalTime;

    public void setTime(Long time) {
        this.totalTime = time;
    }

    private boolean firstCalled = true;
    String lastMsg;
    long startTime;

    public void showSameMsg(String msg, long duration) {
        if (firstCalled) {
            lastMsg = msg;
            show(getTextView(msg), duration, null, null);
            firstCalled = false;
            // 第一次調用的時間
            startTime = (new Date()).getTime();
        } else if (msg.equals(lastMsg)) {
            long endTime = (new Date()).getTime();
            long totalTime = endTime - startTime;
            Log.e("time", "開始時間:" + startTime + "  結束時間: " + endTime + "  總時間"
                    + totalTime);
            // 第二次相同
            if (totalTime > duration) {
                show(getTextView(msg), duration, null, null);
                startTime = endTime;
            }
        }
    }

    /**
     * 顯示一條Toast
     * 
     * @param v
     *            消息內容
     * @param duration
     *            持續時間,單位為毫秒
     */
    public void show(View v, long duration) {
        show(v, duration, null, null);
    }

    /**
     * 顯示一條Toast
     * 
     * @param msg
     *            消息內容
     * @param duration
     *            持續時間,單位為毫秒
     * @param startAnim
     *            入場動畫
     * @param endAnim
     *            離場動畫
     */
    public void show(String msg, Long duration, Animation startAnim,
            Animation endAnim) {
        show(getTextView(msg), duration, startAnim, endAnim);
    }

    /**
     * 顯示一條圖文並存Toast
     * 
     * @param resid
     *            圖片資源
     * @param msg
     *            消息內容
     * @param duration
     *            持續時間,單位為毫秒
     * @param startAnim
     *            入場動畫
     * @param endAnim
     *            離場動畫
     */
    public void show(int resid, String msg, Long duration, Animation startAnim,
            Animation endAnim) {
        show(getView(resid, msg), duration, null, null);
    }

    /**
     * 顯示一條Toast
     * 
     * @param v
     *            顯示的內容
     * @param duration
     *            持續時間,單位為毫秒
     * @param startAnim
     *            入場動畫
     * @param endAnim
     *            離場動畫
     */
    public final void show(final View v, Long duration, Animation startAnim,
            final Animation endAnim) {
        // 反射過程異常時則使用源生Toast
        if (hasReflectException) {
            Toast t = new Toast(mContext);
            t.setView(v);
            t.setDuration(Toast.LENGTH_SHORT);
            t.show();
            // 重新獲取反射對象
            initTN();
            return;
        }

        // 顯示頂層容器控件
        if (mView.getChildCount() == 1)
            showToast();

        // 獲得入場動畫
        if (startAnim == null) {
            startAnim = getStartAnimation();
        }
        v.clearAnimation();
        v.startAnimation(startAnim);
        // 把傳入的toast顯示出來
        mView.addView(v, 0);

        // 延遲後隱藏傳入toast
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                hide(v, endAnim);
            }
        }, duration == null ? TIME_DURATION : duration);

    }

    /**
     * 設置默認背景顏色
     * 
     * @param color
     *            顏色值
     * @param alpha
     *            透明度
     */
    public void setDefaultBackgroundColor(int color, Integer alpha) {
        defaultBackgroundColor = new ColorDrawable(color);
        if (alpha != null)
            defaultBackgroundColor.setAlpha(alpha);
        defaultBackgroundResid = null;
    }

    /**
     * 設置默認背景資源
     * 
     * @param resid
     *            圖片資源文件
     */
    public void setDefaultBackgroundResource(int resid) {
        defaultBackgroundResid = resid;
    }

    /**
     * 設置默認文字顏色
     * 
     * @param color
     */
    public void setDefaultTextColor(int color) {
        defaultTextColor = color;
    }

    /**
     * 重置背景和文字顏色
     */
    public void resetDefaultBackgroundAndTextColor() {
        defaultTextColor = Color.WHITE;
        defaultBackgroundColor = new ColorDrawable(Color.BLACK);
        defaultBackgroundColor.setAlpha(200);
        defaultBackgroundResid = null;
    }

    /**
     * 隱藏指定控件
     * 
     * @param v
     *            需要隱藏的控件
     * @param endAnim
     *            結束動畫
     */
    public final void hide(final View v, Animation endAnim) {
        if (v == null || mView.indexOfChild(v) < 0)
            return;
        // 獲得出場動畫
        if (endAnim == null)
            endAnim = getEndAnimation();
        v.clearAnimation();
        // 開始出場動畫
        v.startAnimation(endAnim);

        // 動畫結束後移除控件
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                if (v == null || mView.indexOfChild(v) < 0)
                    return;
                // 移除指定控件
                mView.removeView(v);
                // 隱藏頂層容器控件
                if (mView.getChildCount() == 1)
                    hideToast();
            }
        }, TIME_END_ANIM);
    }

    /**
     * 獲得一個設置好屬性的TextView
     * 
     * @param msg
     * @return
     */
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    public TextView getTextView(String msg) {
        TextView tv = new TextView(mContext);
        tv.setLayoutParams(lp_WW);
        tv.setText(msg);
        tv.setTextColor(defaultTextColor);
        Drawable background = null;
        if (defaultBackgroundResid != null) {
            background = mContext.getResources().getDrawable(
                    defaultBackgroundResid);
        } else {
            background = defaultBackgroundColor;
        }
        if (currentapiVersion > 10)
            tv.setBackground(background);
        else
            tv.setBackgroundDrawable(background);
        tv.setPadding(5, 5, 5, 5);
        tv.setGravity(Gravity.CENTER);
        return tv;
    }

    /**
     * 獲得一圖片或圖文並存的toast
     * 
     * @param msg
     * @return
     */
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    public LinearLayout getView(int resId, String msg) {
        LinearLayout layout = new LinearLayout(mContext);
        layout.setLayoutParams(new LayoutParams(
                LayoutParams.WRAP_CONTENT,
                LayoutParams.WRAP_CONTENT));
        layout.setOrientation(LinearLayout.VERTICAL);
        layout.setGravity(Gravity.CENTER);
        layout.setPadding(10, 10, 10, 10);
        ImageView imageView = new ImageView(mContext);
        imageView.setLayoutParams(lp_WW);
        imageView.setImageResource(resId);
        layout.addView(imageView);
        if(!TextUtils.isEmpty(msg)){
            TextView tv = new TextView(mContext);
            tv.setLayoutParams(lp_WW);
            tv.setText(msg);
            tv.setTextColor(defaultTextColor);
            tv.setPadding(5, 5, 5, 5);
            tv.setGravity(Gravity.CENTER);
            layout.addView(tv);
        }

        Drawable background = null;
        if (defaultBackgroundResid != null) {
            background = mContext.getResources().getDrawable(
                    defaultBackgroundResid);
        } else {
            background = defaultBackgroundColor;
        }
        if (currentapiVersion > 10)
            layout.setBackground(background);
        else
            layout.setBackgroundDrawable(background);

        return layout;
    }
    /**
     * 獲得入場動畫
     * 
     * @return
     */
    protected Animation getStartAnimation() {
        AlphaAnimation animAlpha = new AlphaAnimation(0, 1);
        animAlpha.setDuration(TIME_START_ANIM);
        animAlpha.setFillAfter(true);
        TranslateAnimation animTrans = new TranslateAnimation(
                Animation.RELATIVE_TO_PARENT, 1.5f,
                Animation.RELATIVE_TO_PARENT, 0f, Animation.RELATIVE_TO_PARENT,
                0f, Animation.RELATIVE_TO_PARENT, 0f);
        animTrans.setDuration(TIME_START_ANIM);
        animTrans.setFillAfter(true);
        animTrans.setInterpolator(new DecelerateInterpolator());

        AnimationSet sets = new AnimationSet(true);
        sets.addAnimation(animAlpha);
        sets.addAnimation(animTrans);

        return sets;
    }

    /**
     * 獲得離場動畫
     * 
     * @return
     */
    protected Animation getEndAnimation() {
        AlphaAnimation animAlpha = new AlphaAnimation(1, 0);
        animAlpha.setDuration(TIME_END_ANIM);
        animAlpha.setFillAfter(true);

        TranslateAnimation animTrans = new TranslateAnimation(
                Animation.RELATIVE_TO_PARENT, 0f, Animation.RELATIVE_TO_PARENT,
                -1.5f, Animation.RELATIVE_TO_PARENT, 0f,
                Animation.RELATIVE_TO_PARENT, 0f);
        animTrans.setDuration(TIME_END_ANIM);
        animTrans.setFillAfter(true);
        animTrans.setInterpolator(new AccelerateInterpolator());
        AnimationSet sets = new AnimationSet(true);
        sets.addAnimation(animAlpha);
        sets.addAnimation(animTrans);
        return sets;
    }

    /* 以下為反射相關內容 */
    Toast mToast;
    Field mTN;
    Object mObj;
    Method showMethod, hideMethod;

    /**
     * 通過反射獲得mTN下的show和hide方法
     */
    private void initTN() {
        mToast = new Toast(mContext);
        mToast.setView(mTopView);
        Class clazz = Toast.class;
        try {
            mTN = clazz.getDeclaredField("mTN");
            mTN.setAccessible(true);
            mObj = mTN.get(mToast);
            showMethod = mObj.getClass().getDeclaredMethod("show",
                    new Class[0]);
            hideMethod = mObj.getClass().getDeclaredMethod("hide",
                    new Class[0]);
            hasReflectException = false;
        } catch (NoSuchFieldException e) {
            hasReflectException = true;
            System.out.println(e.getMessage());
        } catch (IllegalAccessException e) {
            hasReflectException = true;
            System.out.println(e.getMessage());
        } catch (IllegalArgumentException e) {
            hasReflectException = true;
            System.out.println(e.getMessage());
        } catch (NoSuchMethodException e) {
            hasReflectException = true;
            System.out.println(e.getMessage());
        }
    }

    /**
     * 通過反射獲得的show方法顯示指定View
     */
    private void showToast() {
        try {
            // 高版本需要再次手動設置mNextView屬性
            if (currentapiVersion > 10) {
                Field mNextView = mObj.getClass().getDeclaredField("mNextView");
                mNextView.setAccessible(true);
                mNextView.set(mObj, mTopView);
            }
            showMethod.invoke(mObj, new Object[0]);
            hasReflectException = false;
        } catch (Exception e) {
            hasReflectException = true;
            System.out.println(e.getMessage());
        }
    }

    /**
     * 通過反射獲得的hide方法隱藏指定View
     */
    public void hideToast() {
        try {
            hideMethod.invoke(mObj, new Object[0]);
            hasReflectException = false;
        } catch (Exception e) {
            hasReflectException = true;
            System.out.println(e.getMessage());
        }
    }
    public void removeView() {

    }
}

從上面的代碼可以看出:裡面反射來創建Toast,通過反射來獲得mTN下的show和hide方法來控制toast的show和hide,然後獲得handle來處理ui的刷新,代碼通過一些參數來設置toast,比如顯示的文字,背景顏色,背景圖片,顯示的圖片和時長。

然後就是activity_main.xml



    

        
    

    

        
    

    

        
    

    

        
    

    

        
    

    

        
    

    

        

    

    

         
     

為了效果好看點使用CardView,也有點陰影和動畫效果。
接下來就是代碼的示例使用了:

package com.losileeya.toastmaster;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.RotateAnimation;
import android.view.animation.ScaleAnimation;
import android.view.animation.TranslateAnimation;
import android.widget.TextView;
import com.losileeya.toastmaster.view.SuperCustomToast;
import java.lang.ref.WeakReference;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class MainActivity extends AppCompatActivity {
    SuperCustomToast toast;//自定義Toast
    int i = 0;
    final StringBuffer sb = new StringBuffer("默認Toast");
    final String info = "默認Toast-";
    final String sameString = "相同信息Toast";
    Handler mHandler;
    @BindView(R.id.showToast1)
    TextView showToast1;
    @BindView(R.id.showToast2)
    TextView showToast2;
    @BindView(R.id.showToast3)
    TextView showToast3;
    @BindView(R.id.showToast4)
    TextView showToast4;
    @BindView(R.id.showToast5)
    TextView showToast5;
    @BindView(R.id.showToast6)
    TextView showToast6;
    @BindView(R.id.showToast7)
    TextView showToast7;
    @BindView(R.id.showToast8)
    TextView showToast8;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //綁定視圖
        ButterKnife.bind(MainActivity.this);
        //初始化handle
        mHandler = new MyHandler(this);
        //獲取自定義toast的實例
        toast = SuperCustomToast.getInstance(getApplicationContext());

    }

    /**
     *  入場動畫
     */
    private void showAnimate() {

        // 旋轉
        RotateAnimation rAnim = new RotateAnimation(0, 720,
                Animation.RELATIVE_TO_SELF, 0.5f,
                Animation.RELATIVE_TO_SELF, 0.5f);
        rAnim.setDuration(500);
        rAnim.setFillAfter(true);
        // 縮放
        ScaleAnimation sAnim = new ScaleAnimation(0, 1, 0, 1,
                Animation.RELATIVE_TO_SELF, 0.5f,
                Animation.RELATIVE_TO_SELF, 0.5f);
        sAnim.setDuration(500);
        sAnim.setFillAfter(true);
        // 透明度
        AlphaAnimation aAnim1 = new AlphaAnimation(0, 1);
        aAnim1.setDuration(500);
        aAnim1.setFillAfter(true);
        AnimationSet startAnim = new AnimationSet(false);
        startAnim.addAnimation(rAnim);
        startAnim.addAnimation(aAnim1);
        startAnim.addAnimation(sAnim);
        // 移動
        TranslateAnimation animTrans = new TranslateAnimation(
                Animation.RELATIVE_TO_PARENT, 0f,
                Animation.RELATIVE_TO_PARENT, 0f,
                Animation.RELATIVE_TO_SELF, 0f,
                Animation.RELATIVE_TO_SELF, 1f);
        animTrans.setDuration(500);
        animTrans.setFillAfter(true);
        // 透明度
        AlphaAnimation aAnim2 = new AlphaAnimation(1, 0);
        aAnim2.setDuration(500);
        aAnim2.setFillAfter(true);
        AnimationSet endAnim = new AnimationSet(false);
        endAnim.addAnimation(animTrans);
        endAnim.addAnimation(aAnim2);
        toast.show("自定義動畫的Toast-" + i++, null, startAnim, endAnim);
    }



    private static class MyHandler extends Handler {
        private WeakReference activityWeakReference;

        public MyHandler(MainActivity activity) {
            activityWeakReference = new WeakReference<>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            MainActivity activity = activityWeakReference.get();
            if (activity != null) {

            }
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        toast.hideToast();
        toast.mView.removeAllViews();
        toast.initView();
    }


    @OnClick({R.id.showToast1, R.id.showToast2, R.id.showToast3, R.id.showToast4, R.id.showToast5, R.id.showToast6, R.id.showToast7,R.id.showToast8})
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.showToast1:
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        //默認toast
                        toast.show(info + i++);
                    }
                });

                break;
            case R.id.showToast2:
                // 持續5秒的toast
                toast.showSameMsg(sameString, 5000);
                break;
            case R.id.showToast3:
                //帶背景色Toast
                toast.setDefaultBackgroundColor(Color.RED, 200);//Toast背景
                toast.setDefaultTextColor(Color.BLUE);//文字顏色
                toast.show("帶有背景色Toast");
                break;
            case R.id.showToast4:
                //給Toast添加背景圖片
                toast.setDefaultBackgroundResource(R.drawable.bg);
                toast.setDefaultTextColor(Color.BLACK);
                toast.show("背景圖片的Toast");
                break;
            case R.id.showToast5:
                //給Toast加動畫
                showAnimate();

                break;
            case R.id.showToast6:
                //帶圖片的Toast
                toast.setDefaultBackgroundResource(R.drawable.frame_bg_theme_light);
                toast.show(R.drawable.tips_smile, "", null, null, null);
                break;
            case R.id.showToast7:
                //圖文混合的toast
                toast.setDefaultTextColor(Color.RED);
                toast.setDefaultBackgroundResource(R.drawable.frame_bg_theme_light);
                toast.show(R.drawable.tips_smile, "我笑了", null, null, null);
                break;
            case R.id.showToast8:
                //自定義布局Toast
                toast.setDefaultTextColor(Color.RED);
                toast.show(info + i++, R.layout.super_toast_theme_light,
                        R.id.content_toast, MainActivity.this);
                break;
        }
    }
}

上面的代碼呢就是對8種toast的效果的展示,基本上也能適合開發的所有場景了,實在不行的話那麼你就使用snackbar咯,效果或許不好,但是也還是能學到一些東西的。

注意:

由於使用的butterknife5.0.1我手賤更新到了8.0.1,差點被坑了
我是這樣做的:

compile ‘com.jakewharton:butterknife:8.0.1’

然後代碼也能使用:@BindView,@OnClick特麼怎麼出鬼了,提示unused(木有使用) ,木有辦法只能去github上了,然後改成這樣

apply plugin: 'com.neenbedankt.android-apt'
dependencies {
     compile 'com.jakewharton:butterknife:8.0.1'
     apt 'com.jakewharton:butterknife-compiler:8.0.1'
   }  

然後工程的也要改:

buildscript {
      repositories {
         jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.0.0'
        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
    }
}

總結

對toast的源碼翻出來一部分,然後跟我們一般的toast的封裝還是有些不同,當然封裝一下toast對開發的效率還是能夠提高的 ,代碼中用到了動畫有溫習了一下,學習就是這樣從難到易。

好了,所有的講解就到這裡了,能力有限見丑了,就到這裡。感覺不錯麻煩幫頂一下,贊一個,哪裡有問題指出來。
 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved