Android Window理解(3.2)---子窗口Menu及系统Toast创建

一、Context Menu创建显示

Context Menu一般从两种方式显示,首先是当用户长按view,如果该View的事件没有被消耗,则回显示设置的Menu。其次是在Activity中如何注册了listener提供菜单信息,开发者可以调用显示Menu。

(1)Context Menu中的类关系

  • Menu:描述对于整个菜单应该具有的操作接口。MenuBuilder是对于Menu的实现,是同时面向情景菜单和选项菜单的。

  • MenuItem:描述一个菜单条目应该具有的操作接口。

  • ContextMenuBuilder:该类中包含List变量保存菜单中的每一个条目信息,并提供情景菜单特有实现接口。侧重于菜单内容操作。

  • MenuDialogHelper:用于根据菜单内容创建对应窗口显示出来。

(2)ContextMenu触发过程

如图总结:

  • ContextMenu触发显示操作主要两种方式。第一是长按view事件未处理时有机会弹出,第二是在Activity中开发者调用view.openContextMenu()时弹出,在此种方式下必须是先调用registerForContextMenus(View)为指定view注册Listener为该Activity同时覆写方法onCreateContextMenu()为该View提供菜单显示的内容。

  • 以上两种方式最终调用view.showContextMenu()接着递归调用到最终DecorView.showContextMenuForChild()

(3)ContextMenu显示过程

如上图存在两种方式弹除一个ContextMenu

1.用户长按View并且其内部未消耗该事件转而调用View.showContextMenu()弹窗菜单。在Activity中开发者为View注册接口覆写方法为View提供菜单内容,使用Activity.openContextMen(View)为该View显示菜单。

2.以上两种方式最终都会调用到View.getParent().showContextMenuForChild(),而该方法最终递归调用到DecorView.showContextMenuForChild(View)

3.在DecorView.showContextMenuForChild(View)中,首先新建类型为ContextMenuBuilder的mContextMenu对象负责管理菜单中的内容。接着就调用ContextMenuBuilder.show()。

4.在ContextMenuBuilder.show()完成两件主要事情:

  • 首先去调用对应View.createContextMenu()方法完成对菜单显示内容的添加。该方法中通过三种方式(View覆写的onCreateContextMenu()、view注册的listener中的方法实现、调用其父View的同名方法)获取菜单内容。

  • 新建MenuDialogHelper对象helper,调用MenuDialogHelper.show()完成实际的显示菜单任务。在该show方法中会新建一个Dialog同时修改该Dialog的对于的Window.LayoutParams参数type为子Window类型。最后调用Dialog.show()显示出来。

至此就是ContextMenu的显示过程。

二、OptionsMenu 创建显示

启动选项菜单两种方式:一是点击Menu按键、二是Activity中等调用PhoneWindow.openOptionsMenu()。两种方式主要流程一样。

当Menu按键按下未释放时执行onKeyDown(),在该方法中主要完成:1.新建获取PanelFeatureState对象获取并赋值createPanelView。2.创建MenuBuilder对象,依次调用CallBack的onCreatePanelMenu()和onPreparePane()方法为该菜单设置数据吗,此处CallBack是Activity对象。

当Menu按键释放时执行onKeyUp(),在该方法中完成:1.创建菜单窗口的DecorView。2.添加具体菜单View到DecorView中。3.使用WM添加菜单窗口显示。

PhoneWindow.PanelFeatureState类介绍:

该类包含了该Window中所有的子窗口,开发者可以为Activity中的Window类添加任意不同特色的子窗口,所有这些窗口的信息都保存在PanelFeatureState[] mPanels变量中。

PanelFeatureState包含以下重要变量:

  • DecorView decorView:每个特色窗口的根视图

  • View createPanelView:开发者在回调接口中设置的窗口视图,可以为空

  • View showPanelView:菜单窗口最终要显示的视图

  • MenuBuilder menu:选项菜单中的菜单实体管理菜单内容

注意:OptionsMenu窗口类型仍然为子窗口,其仅仅是一个View并未真正新创建窗口。

选项菜单的st对象中的menu对象一直保存在内存中,而情景菜单中的menu对象不能。

三、系统窗口Toast创建显示

当客户端请求添加窗口时,在WmS这端会收先根据窗口类型检查权限。调用mPolicy.checkAddPermission()方法。

以下是创建显示Toast原理图:

使用Toast弹窗,外部提供的接口是Toast.makeText().show()方法,简单总结:

1.makeText()用于创建一个Toast对象,创建一个View对象放置开发者设置的text。

2.接着调用show()方法,在该方法内部会IPC调用NotificationManagerService.enqueueToast()方法向mToastQueue中加入客户端需要显示的Toast对象。

3.接着执行到showNextToastLocaked()获取mToastQueue中的最近Tosat对象IPC回调TN.show()使用WIndowManager.addView()将Toast显示到屏幕上。同时使用Handler发起一个异步回调,回调的间隔来自开发者指定的常量。

4.触发异步回调此时执行到cancleToastLocaked()方法,在该方法中依然IPC回调TN.hide()删除这个Toast将其影藏。同事获取mToastQueue的对象接着进行下一个Toast的显示。

以上就是Toast的串行显示的过程。

四、token变量含义

下表是Android有关token的信息:

Activity中的mToken

Activity中的mToken实际上是在启动Activity时,创建的对象ActivityClientRecord引用,其原型是Binder。ActivityClientRecord中也引用一个传入token,该token是AMS远程为Activity创建的标识。

Window对象中的mAppToken

每个Window都有一个mAppToken,在Window对象中的mAppToken其实就是来自Activity中的mToken,但是存在一个Window对象没有对应一个Activity,所有此时mAppToken为空。

WindowManager.LayoutParams中的token

  • 如果创建的窗口是应用窗口,token的值就是Window中的mAppToken相同,随后会被修改为指向一个W对象的,用于WmS通过IPC控制窗口。

  • 如果创建的是子窗口,token为其父窗口的W对象。

  • 如果创建的是系统窗口,token为空。

View中的token

View中的mAttachInfo来自ViewRooytImpl构造时生成的mAttachInfo。同一窗口包含的所有View的mAttachInfo都相同。

mAttachInfo中包含3个token:

  • mWindowToken:该窗口对应的W对象

  • mPanelParentWindowToken:如果该窗口是子窗口该变量即为父窗口的W对象。与mWindowToken互斥。

  • mWindow:是一个IWindow对象。mWindowToken = IWindow.asBinder()

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值