Android Window理解(3.1)---子窗口创建过程:Dialog、PopupWindow

创建子窗口

父子窗口关系标识:

  • View.AttachInfo.mPanelParentWindowToken变量、在ViewRootImpl.setView中设置。

  • Window.mHasChild和Window.mContainer变量、代表Activity所在Window存在父Window。只在TabActivity中使用。

除此之外,对于Dialog等创建的Window为默认类型Application时,会设置Window.token为所在Activity的Window的token,其实就是Activity的token值。

一、Dialog创建过程

Android Window理解(3.1)---子窗口创建过程:Dialog、PopupWindow_第1张图片

Dialog的使用过程,首先构造对象然后调用方法显示。

(1)构造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处理异步消息回调。

(2)显示Dialog过程:

1.调用show()函数显示Dialog到界面。

2.使用mShowing控制如果已经显示了Dialog,直接设置mDercor可见返回。

3.确保没有显示Dialog,首先回调onCreate()函数,开发者在这个方法中需要调用setContentView()设置Dialog显示的View。接着回调onStart()函数,然后获取开发者设置的View即mDecor。

4.获取Window对应的WIndowManager.LayoutParams参数,最后调用mWindowManager.add()设置显示View,异步回调接口sendShowMessage()。

(3)WindowManager.addView()过程

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创建显示

PopupWindow内部并不创建Window,而是在Activity的Window基础上添加View。

(1)PopupWindow创建过程

Android Window理解(3.1)---子窗口创建过程:Dialog、PopupWindow_第2张图片

以上是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。

(2)PopupWindow显示过程

Android Window理解(3.1)---子窗口创建过程:Dialog、PopupWindow_第3张图片

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内部去完成。

你可能感兴趣的:(安卓源码分析,android,window,dialog)