父子窗口关系标识:
View.AttachInfo.mPanelParentWindowToken变量、在ViewRootImpl.setView中设置。
Window.mHasChild和Window.mContainer变量、代表Activity所在Window存在父Window。只在TabActivity中使用。
除此之外,对于Dialog等创建的Window为默认类型Application时,会设置Window.token为所在Activity的Window的token,其实就是Activity的token值。
Dialog的使用过程,首先构造对象然后调用方法显示。
1.调用Dialog构造函数传入三个参数context:一般是Activity对应的context,theme:使用的主题id,最后一个是否需要创建ContextThemeWrapper对象,这个对象也是一个壳正在的实现是第一个参数context。
2.构造函数中首先初始化变量mContext,根据传入参数生成或者直接赋值。
3.获取一个WindowManager引用,由于context来自Activity所以这个WM引用就是Activity中的WM对象。
4.生成PhoneWindow对象类型仍然为默认的Application类型,设置Window必要参数,设置回调与Window通信。
5.生成一个Handler处理异步消息回调。
1.调用show()函数显示Dialog到界面。
2.使用mShowing控制如果已经显示了Dialog,直接设置mDercor可见返回。
3.确保没有显示Dialog,首先回调onCreate()函数,开发者在这个方法中需要调用setContentView()设置Dialog显示的View。接着回调onStart()函数,然后获取开发者设置的View即mDecor。
4.获取Window对应的WIndowManager.LayoutParams参数,最后调用mWindowManager.add()设置显示View,异步回调接口sendShowMessage()。
1.在mWindowManager.addView()内部其实真正是调用mGlobal.addView(view,params,mDisplay,mParentWindow)。因为这个WindowManager来自Activity,所以此方法传入的参数mParentWindow是Activity对于的Window对象。
2.mGlobal.addView()中因为mParentWindow不为空,需要调用mParentWindow.adjustLayoutParamsForSubWindow()设置依附Window的token和title。在该函数中两种处理方式:如果Window类型为子Window则设置其token为父Window对应的DecorView的W对象的Binder引用,如果不是子Window类型设置其token为依附的Activity的token。
3.新建ViewRootImpl对象root,调用root.setView()将Dialog对应的View显示出来。
注意:Dialog对应生成的Window类型仍然为Application。
PopupWindow内部并不创建Window,而是在Activity的Window基础上添加View。
以上是PopupWindow创建过程,存在两种类型构造函数。
对于第一种构造函数主要是以下步骤:
1.赋值Context和WM,因为PopupWindow在Activity中创建所以,以上两个变量均来自Activity内部。所有PopupWindow使用到显示View的Window仍然是Activity的Window对象。
2.获取BackGround的drawable和弹窗动画资源id。
对于这种创建方式需要显式调用setContentView()设置真正显示的View。
对于第二种构造函数:
1.也是赋值Context和WM,和第一种相同。
2.根据传入参数设置显示的View及其高宽和是否获取焦点。
总之,不论是哪种方式都需要设置变量Context和WM。
PopupWindow的显示仍然提供两种方式:在指定View下方显示和在指定坐标出显示。
对于第一种在指定View下方显示:
1.首先生成布局参数WindowManager.LayoutParams,设置该参数的type和token,注意此处的type是子类型。
2.准备需要弹出显示的View,这里分为两种情况处理。其一如果是存在background的drawable需要新建一个PopupViewContainer(其实是个FrameLayout)add需要现实的View同时设置背景。其二如果不存在则直接赋值。
3.设置View显示的位置。首先调用findDropDownposition()设置需要显示的位置到布局参数中,接着调用updateAboveAnchor()设置在指定View之上显示时的Drawable。
4.显示View。使用invokePopup()通过WM显示View到指定的位置之下。
对于第二种在指定位置显示其实和第一种步骤相仿,只是在第三步的时候设置View显示的位置时候,直接根据传入参数赋值布局参数即可,其他步骤相同。
注意:PopupWindow通过以上方式创建显示成功,但是仍然不能自动处理系统按键,所有的消息处理必须由mContentView内部去完成。