Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android Toast進階——自定義Toast

Android Toast進階——自定義Toast

編輯:關於Android編程

目錄結構

目錄結構 前言 進階目標 控制Toast顯示時間 修改Toast動畫效果


前言

CSDN竟然支持Markdown語法了,對我這種懶得自己搭建博客的人確實是好消息,再復習Markdown語法的同時,我准備把之前寫的一篇Android Toast進階用Markdown語法重寫一遍。


進階目標

上一篇博客我們學習了Toast的源碼,了解了Toast從顯示到消失的全過程,學習鏈接:Android Toast源碼分析。俗話說的好,學以致用。我們學習Toast源碼不是用來炫技的,而是用來了解Toast原理,從而真正解決我們問題的。下面我就提兩個業務中可能遇到的跟Toast相關的真實問題,看看學習了Toast源碼之後,該如何解決這些問題。兩個問題是:
1. 如何自定義Toast的顯示時間。
2. 如何修改Toast的出現動畫。
接下來,我們分別講解閱讀了Toast源碼之後,如何解決這兩個業務中真實遇到的問題。


控制Toast顯示時間

通過對Toast源碼的學習,我們知道Toast的顯示和消失是NotificationManagerService調用TN類的show和hide方法實現的,而Toast的顯示時間的長短則跟Handler發送消息的延遲時間相關。具體源碼如下:

private void scheduleTimeoutLocked(ToastRecord r)
{
    mHandler.removeCallbacksAndMessages(r);
    Message m = Message.obtain(mHandler, MESSAGE_TIMEOUT, r);
    long delay = r.duration == Toast.LENGTH_LONG ? LONG_DELAY : SHORT_DELAY;
    mHandler.sendMessageDelayed(m, delay);
}

之前Toast源碼裡也講過,為什麼Toast的桌面顯示時間只能是2s和3.5s,關鍵就是在於long delay變量的延遲時間只能是2s和3.5s。因此,如果你是Android操作系統的開發人員,你可以直接修改Android Framework層的NotificationManagerService類代碼,將LONG_DELAY和SHORT_DELAY改成你想要的時間間隔。但是,這種做法的弊端很明顯。首先,你可能只是一個小小的應用層開發工程師,只能改動應用層代碼。其次,就算修改NotificationManagerService,也只能改動LONG_DELAY和SHORT_DELAY兩個變量,無法做到隨意修改顯示時間。
弊端這麼多,那我們應用層開發工程師該怎麼辦呢?答案也很簡單,仿照Toast源碼,我們自己造個輪子,自定義一個Toast,這樣我們肯定就可以控制Toast的顯示時間了。通過源碼我們知道,Toast是基於WindowManager來顯示的,那我們完全可以撸一個自定義Toast出來,源碼如下:

import android.content.Context;
import android.graphics.PixelFormat;
import android.os.Handler;
import android.os.Message;
import android.view.Gravity;
import android.view.View;
import android.view.WindowManager;
import android.widget.Toast;

public class ToastCustom {
    private static final int MESSAGE_TIMEOUT = 2;
    private WindowManager wdm;
    private double time;
    private View mView;
    private WindowManager.LayoutParams params;
    private WorkerHandler mHandler;

    private ToastCustom(Context context, String text, double time) {
        wdm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        mHandler = new WorkerHandler();

        Toast toast = Toast.makeText(context, text, Toast.LENGTH_LONG);
        mView = toast.getView();

        params = new WindowManager.LayoutParams();
        params.height = WindowManager.LayoutParams.WRAP_CONTENT;
        params.width = WindowManager.LayoutParams.WRAP_CONTENT;
        params.format = PixelFormat.TRANSLUCENT;
        params.windowAnimations = toast.getView().getAnimation().INFINITE;
        params.type = WindowManager.LayoutParams.TYPE_TOAST;
        params.setTitle("Toast");
        params.gravity = Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL;
        params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;

        this.time = time;
    }

    public static ToastCustom makeText(Context context, String text, double time) {
        ToastCustom toastCustom = new ToastCustom(context, text, time);
        return toastCustom;
    }

    public void show() {
        wdm.addView(mView, params);
        mHandler.sendEmptyMessageDelayed(MESSAGE_TIMEOUT, (long) (time * 1000));
    }

    public void cancel() {
        wdm.removeView(mView);
    }

    private class WorkerHandler extends Handler {
        @Override
        public void handleMessage(Message msg)
        {
            switch (msg.what)
            {
                case MESSAGE_TIMEOUT:
                    cancel();
                    break;
            }
        }
    }
}

原理很簡單,利用WindowManager來顯示Toast,然後利用Handler機制發送延遲消息控制WindowManager再將Toast刪除。需要注意一點:這裡自定義Toast的Handler用的也是主線程的Looper,子線程調用該自定義Toast需要增加Looper.prepare()和Looper.loop()代碼。


修改Toast動畫效果

Android原生的Toast類並沒有提供給我們設置動畫效果的接口,每個Android原生的Toast的動畫效果都是在TN類中定義好的com.android.internal.R.style.Animation_Toast,因此,如果你想要修改Android?Toast的動畫效果,還是需要自己撸一個Toast,修改一下params.windowAnimations變量的內容即可。接下來,讓我們先自定義一個動畫效果。在style.xml文件中定義一個新的style,xml內容如下:

然後在anim文件夾下面增加兩個動畫效果文件,分別為enter_anim.xml和exit_anim.xml。

enter_anim.xml







exit_anim.xml




然後,修改一下自定義Toast代碼中的params.windowAnimations變量即可:

params.windowAnimations = com.example.photocrop.R.style.custom_toast_anim_view;
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved