Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android初級教程通過簡要分析“土司”源碼

Android初級教程通過簡要分析“土司”源碼

編輯:關於Android編程

由於系統自帶的土司瞬間即逝,而且非常難看。因此我們就希望自定義自己的土司風格。有些實例就是基於自定義土司完成的,例如金山衛士的火箭發射,基本原理就是個土司。但是在做出自己的土司風格之前,還是要簡要分析一下土司的源碼。看看系統自帶的土司是如何實現的。此篇文章,對土司源碼進行簡要分析(由於筆者能力有限,全部源代碼每一行都看懂不切實際,其實有些時候沒必要太過追求細節,沒必要追求每一行都看懂,能抓住源碼的主要思路與核心代碼就夠了),理出系統實現土司的原理,和它的核心代碼。在Android簡易實戰專欄裡的 第十話,會舉一個自定義土司的實例。來對這種知識點加深印象。

 

1,分析:看系統的Toast是怎麼做出來

Toast.makeText(getApplicationContext(), "111", 1).show();

首先看一下土司的構造函數源碼:
    public Toast(Context context) {//傳遞了一個上下文對象
 mContext = context;//被上下文對象給了mContext
 mTN = new TN();//在這裡創建TN對象
        //給TN兩個屬性值(這裡沒必要追求太深入具體)
 mTN.mY = context.getResources().getDimensionPixelSize(
 com.android.internal.R.dimen.toast_y_offset);
 mTN.mGravity = context.getResources().getInteger(
 com.android.internal.R.integer.config_toastDefaultGravity);
 } 
在這裡只需要記住一點很重要的地方,創建土司構造函數,生成了一個TN對象就行,因為後邊會用的到它。
 a, makeText方法
        //記得上邊具體意義哦:構造土司對象,創建TN的實例 mTN = new TN();
        Toast result = new Toast(context);

        LayoutInflater inflate = (LayoutInflater)
                context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View v = inflate.inflate(com.android.internal.R.layout.transient_notification, null);//設置了一個自定義view布局(就是土司的布局)
        //土司顯示的文本框
        TextView tv = (TextView)v.findViewById(com.android.internal.R.id.message);
        tv.setText(text);//設置文本

        result.mNextView = v;//把當前土司的view給mNextView屬性
        result.mDuration = duration;//土司顯示的時長

        return result;

   b,show方法
        if (mNextView == null) {//只要設定了view九部委null這裡不會執行
            throw new RuntimeException("setView must have been called");
        }

        INotificationManager service = getService();//獲取INotificationManager對象
        String pkg = mContext.getPackageName();//獲取包名
        TN tn = mTN;//注意這個TN對象,開始提到過
        tn.mNextView = mNextView;//把土司的view給了TN的mNextView屬性

        try {
            service.enqueueToast(pkg, tn, mDuration);//這當你寫多條土司時,會排隊顯示,其實都把每個土司對應的view放入了隊列裡面了
        } catch (RemoteException e) {
            // Empty
        }
   c, TN的源代碼
       TN的構造函數: 初始化LayoutParams

c, TN的源代碼 TN的構造函數: 初始化LayoutParams       TN() {//再想一開始的時候,土司構造函數創建,內部實例化這個TN構造。不用再乎太多細節,這裡其實是給土司設置一些參數,可以看到 //獲取了一個 windowmanager實例。並給其設置對齊方式、動畫、標題等等 // XXX This should be changed to use a Dialog, with a Theme.Toast // defined that sets up the layout params appropriately. final WindowManager.LayoutParams params = mParams; params.height = WindowManager.LayoutParams.WRAP_CONTENT; params.width = WindowManager.LayoutParams.WRAP_CONTENT; params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; params.format = PixelFormat.TRANSLUCENT; params.windowAnimations = com.android.internal.R.style.Animation_Toast; params.type = WindowManager.LayoutParams.TYPE_TOAST; params.setTitle("Toast"); }

     public void handleShow() {
        if (localLOGV) Log.v(TAG, "HANDLE SHOW: " + this + " mView=" + mView
                + " mNextView=" + mNextView);
        if (mView != mNextView) {
            // remove the old view if necessary
            handleHide();
            mView = mNextView;
            mWM = WindowManagerImpl.getDefault();//獲取WindowManager對象
            final int gravity = mGravity;
            mParams.gravity = gravity;
            if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.FILL_HORIZONTAL) {
                mParams.horizontalWeight = 1.0f;
            }
            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.FILL_VERTICAL) {
                mParams.verticalWeight = 1.0f;
            }
            mParams.x = mX;
            mParams.y = mY;
            mParams.verticalMargin = mVerticalMargin;
            mParams.horizontalMargin = mHorizontalMargin;
            if (mView.getParent() != null) {
                if (localLOGV) Log.v(TAG, "REMOVE! " + mView + " in " + this);
                mWM.removeView(mView);
            }
            if (localLOGV) Log.v(TAG, "ADD! " + mView + " in " + this);
            //土司顯示的真正代碼
            mWM.addView(mView, mParams);//使用WindowManager對象,把土司的view以及參數加載進這個對象(這裡看出,土司不是基於activity的,而是基於window的)
            trySendAccessibilityEvent();
        }
    }

2,分析最終結果(怎麼添加toast):

 土司是加載到WindowManager中
  mView 土司顯示的View
  mParams 土司在windowmanager中顯示的參數配置
  mWM.addView(mView, mParams);
好的,如果看得費勁,可以理解最後一句代碼吧?
mWM.addView(mView, mParams);
就是自定義一個view,再給土司在Windowmanager中的顯示參數做一些配置,最後加載到WindowManager中就行了。

在Android簡易實戰專欄裡的 第十話中,會把模擬金山手機衛士那個小火箭發射的案例,通過這個案例,相信能做出更好的自定義土司效果。

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