zoukankan      html  css  js  c++  java
  • 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简易实战专栏里的  第十话中,会把模拟金山手机卫士那个小火箭发射的案例,通过这个案例,相信能做出更好的自定义土司效果。

  • 相关阅读:
    HDU5418.Victor and World(状压DP)
    POJ2686 Traveling by Stagecoach(状压DP)
    POJ3254Corn Fields(状压DP)
    HDU5407.CRB and Candies(数论)
    CodeForces 352D. Jeff and Furik
    CodeForces 352C. Jeff and Rounding(贪心)
    LightOj 1282 Leading and Trailing
    Ural 1057. Amount of Degrees(数位DP)
    HDU 2089 不要62 (数位DP)
    HDU5366 The mook jong (DP)
  • 原文地址:https://www.cnblogs.com/wanghang/p/6299631.html
Copyright © 2011-2022 走看看