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

  • 相关阅读:
    vs项目,点击.sln文件时出错:“项目所需的应用程序未安装,确保已安装项目类型(.csproj)的应用程序”解决办法
    Oracle VM VirtualBox各种显示模式切换 热键
    ajax从asp后台获取数据
    js获取页面的宽度
    SharePoint列表数据展现方法
    select改变执行操作
    SharePoint中删除列表记录
    HP EliteBook 8770p打开Vt-x
    SPlist按PID层级顺序导入datatable
    Excel导入DataTable
  • 原文地址:https://www.cnblogs.com/wanghang/p/6299631.html
Copyright © 2011-2022 走看看