android界面框架Window.docx
- 文档编号:29620577
- 上传时间:2023-07-25
- 格式:DOCX
- 页数:18
- 大小:23.18KB
android界面框架Window.docx
《android界面框架Window.docx》由会员分享,可在线阅读,更多相关《android界面框架Window.docx(18页珍藏版)》请在冰豆网上搜索。
android界面框架Window
android界面框架-Window
从纯sdk及framwork的角度看,android中界面框架相关的类型有:
Window,WindowManager,View等。
下面就以这几个类为出发点来概览下安卓开发的“界面架构”。
Window
该类接触不多,和它密切相关的View类就比较熟悉了。
Window和View的关系
View是可视界面上的一个矩形区域,它显示内容并接收各种交互事件。
所有View形成一个ViewTree这样的结构,对应任何一个界面通过sdk自带的hierarchyviewer工具就可以看到所有View对象形成的视图树的形象的结构图,相信都不会陌生。
一般的,开发工作主要是利用系统及自定义控件组合完成各种界面,所以理解View的使用和原理更重要些。
再进一步,以ViewTree为整体,再看它和window,系统服务之间的关系可以从整体上把握android中界面框架。
Window类的描述如下:
Window:
Abstractbaseclassforatop-levelwindowlookandbehaviorpolicy.Aninstanceofthisclassshouldbeusedasthetop-levelviewaddedtothewindowmanager.ItprovidesstandardUIpoliciessuchasabackground,titlearea,defaultkeyprocessing,etc.
Window表示“窗口”的概念,类似桌面OS中的窗口的概念,它是对用户界面的一个逻辑划分。
可以参考下Windows编程中对Window类的描述是:
“Thepointofinteractionbetweenauserandastandaloneapplicationisawindow.”。
每个窗口对应一个独立的交互(可以是完整屏幕大小的)界面。
可以认为窗口是系统区分不同界面(不同app,或者同一app的不同Activity等)的一个单位。
窗口之间可以包含(容器和子窗口),可以重叠(窗口具有z轴深度)。
窗口本身没有显示内容的能力,它包含一个顶级的View对象来持有一棵ViewTree。
一句话概况:
窗口是一个独立的可交互界面,不同窗口叠加显示,窗口包含View来显示内容。
android中的UI就是View组成的ViewTree来表达的,rootview或者说顶部(toplevel)的View对象作为对整个ViewTree执行消息传递,测量,布局和绘制等遍历操作的全局入口,持有此rootview就相当于持有对应的组成界面内容的ViewTree。
有一点就是,Window是一个框架层的概念,整个android中的“各种界面”是不同类型的Window对象。
但是在应用层,我们创建不同的界面就是提供不同的“内容”View对象,然后指定其Window类型,而界面的创建,更新和关闭是通过操纵Window所包含的要显示的顶级View,而不会直接去操控Window对象。
创建Window
在一个新窗口显示一个View最简单的过程如下:
privatevoidopenNewWindow(){
Buttonbutton=newButton(this);
button.setText("ButtonOnNewWindow");
WindowManager.LayoutParamsparams
=newWindowManager.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
params.gravity=Gravity.LEFT|Gravity.TOP;
params.x=220;
params.y=320;
params.type=WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
params.flags=WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
WindowManagerwindowManager=(WindowManager)getSystemService(WINDOW_SERVICE);
windowManager.addView(button,params);
}
创建Window是通过WindowManager实现的,addView(Viewview,WindowManager.LayoutParamsparams)方法接收要展示的rootview和窗口布局相关的参数。
执行上面的代码会创建一个新的窗口,并在屏幕坐标(220,320)的位置放置了一个Button。
应用层要做的就是准备好Button对象,然后设置好相关布局参数,而Window对象的创建本身最终是通过系统服务完成的。
类似Activity那样,Window对象的创建不是new出来的。
窗口的创建,更新和关闭操作都是WindowManager的工作。
实际开发中很少和Window直接打交到。
比如Activity对应一个窗口,但是对它的界面的各种操作好像都和Window无关,因为Window的确够“底层”了。
窗口类型
前面说过,安卓中的界面划分为一个个窗口,系统运行中各个不同的窗口可以叠加显示。
和叠加相关的属性就是Z-ordered,它是正整数。
通过Z-ordered值,系统来决定这些Window的覆盖顺序。
但实际上并不是通过指定Z-ordered值来直接控制窗口的层叠,而是,系统提供了一组常量,被表示为窗口类型,不同窗口类型的常量对应一个Z-ordered的值范围,然后其它地方通过为Window指定type来间接控制其Z-ordered。
Window类有一个setType的方法正是做这件事情的。
不过在创建Window时就需要为其指定type,而我们不直接接触Window对象,WindowWindowManager.LayoutParam有一个type的变量,在通过WindowWindowManager.addView方法创建窗口时,窗口布局参数中指定需要的type——窗口类型——这是必须的,而且Windowtypecannotbechangedafterthewindowisadded。
窗口类型有:
系统窗口:
如状态栏,Toast那样的,常量如TYPE_SYSTEM_xx的。
应用窗口:
就是Activtiy。
子窗口:
Dialog这样的,需要依附(attach)到其它窗口(作为子窗口的container,如Activity)。
WindowManager.LayoutParams有个flags的属性,用来控制窗口的可见性,透明,是否可以获得焦点等显示和交互的有关状态。
Window相关属性和方法
接下来直面Window类。
它是一个抽象类,目前只有PhoneWindow是其实现类。
可以通过下面截取的类型定义的代码片段对Window有个感官认识:
publicabstractclassWindow{
//一系列的FEATURE_xx常量,还记得在Activity中requestWindowFeature方法吗?
publicstaticfinalintFEATURE_xxx
/**
*APIfromaWindowbacktoitscaller.
*Thisallowstheclienttointerceptkey
*dispatching,panelsandmenus,etc.
*/
privateCallbackmCallback;
//Theinterfacethatappsusetotalktothewindowmanager.
privateWindowManagermWindowManager;
privateWindowmContainer;
privateWindowmActiveChild;
//Thecurrentwindowattributes.
privatefinalWindowManager.LayoutParamsmWindowAttributes=
newWindowManager.LayoutParams();
/**
*TheIDthatthemainlayoutintheXMLlayoutfileshouldhave.
*/
publicstaticfinalintID_ANDROID_CONTENT=com.android.internal.R.id.content;
/**
*APIfromaWindowbacktoitscaller.Thisallowstheclientto
*interceptkeydispatching,panelsandmenus,etc.
*/
publicinterfaceCallback{
publicbooleandispatchTouchEvent(MotionEventevent);
publicvoidonAttachedToWindow();
//...
}
publicabstractLayoutInflatergetLayoutInflater();
publicabstractvoidsetContentView(Viewview,ViewGroup.LayoutParamsparams);
/**
*Retrievethetop-levelwindowdecorview(containingthestandard
*windowframe/decorationsandtheclient'scontentinsideofthat),which
*canbeaddedasawindowtothewindowmanager.
*
*
Notethatcallingthisfunctionforthefirsttime"locksin"
*variouswindowcharacteristicsasdescribedin
*{@link#setContentView(View,android.view.ViewGroup.LayoutParams)}.
*
*@returnReturnsthetop-levelwindowdecorview.
*/
publicabstractViewgetDecorView();
publicabstractvoidsetTitle(CharSequencetitle);
publicvoidsetIcon(@DrawableResintresId){}
}
有三个值得关注的:
Window.Callback
该接口使得依靠(可以确定的是所有界面都是通过Window展示的)Window来显示内容的其它对象——主要就是Activity——接收Window发送的交互等事件和消息回调。
例如Activity.onAttachedToWindow()这样的回调。
getDecorView
DecorView就是和Window关联的用来显示内容的ViewTree的root。
所有地方都使用Window来显示内容,不同的Window使用者会需要不同的DecorView,比如Activity就需要DecorView本身具备ActionBar这类的“界面装饰部分”。
而Dialog明显没有。
setContentView
Window显示的自定义内容。
Activity中的setContentView正是调用关联的Window对象的此方法。
将界面内容附加到DecorView作为其子树。
PhoneWindow
PhoneWindow作为目前Window的唯一子类,它的大致定义如下:
publicclassPhoneWindowextendsWindow{
//Thisisthetop-levelviewofthewindow,containingthewindowdecor.
privateDecorViewmDecor;
//Thisistheviewinwhichthewindowcontentsareplaced.Itiseither
//mDecoritself,orachildofmDecorwherethecontentsgo.
privateViewGroupmContentParent;
privateTextViewmTitleView;
privateImageViewmLeftIconView;
privateActionBarViewmActionBar;
@Override
publicvoidinjectInputEvent(InputEventevent){
getViewRootImpl().dispatchInputEvent(event);
}
privateViewRootImplgetViewRootImpl(){
if(mDecor!
=null){
ViewRootImplviewRootImpl=mDecor.getViewRootImpl();
if(viewRootImpl!
=null){
returnviewRootImpl;
}
}
thrownewIllegalStateException("viewnotadded");
}
privatefinalclassDecorViewextendsFrameLayout{
//...
}
}
DecorView
PhoneWindow的内部类DecorView作为Window关联的ViewTree的rootview。
它用来放置ActionBarView,Title和Icon等一些在Activity中经常访问得到的界面元素。
而应用自身提供的contentView是作为DecorView的childView存在的。
ViewRootImpl
从View组成ViewTree的角度看,任意的ViewGroup子类都可以做为root,但Window操作ViewTree时需要对rootview做特殊对待,ViewRootImpl正是用来表达rootview,是Window和ViewTree之间的交互接口:
/**
*Thetopofaviewhierarchy,implementingtheneededprotocolbetweenView
*andtheWindowManager.Thisisforthemostpartaninternalimplementation
*detailof{@linkWindowManagerGlobal}.
*
*{@hide}
*/
@SuppressWarnings({"EmptyCatchBlock","PointlessBooleanExpression"})
publicfinalclassViewRootImplimplementsViewParent{
//...
}
在View中方法ViewRootImplgetViewRootImpl()可以获得一个View关联的ViewRootImpl对象。
在ViewTree关联到Window后,每个View会获得一个AttachInfo对象,里面保存了rootView和ViewRootImpl这样的对象来访问根视图。
至于ViewRootImpl到底有哪些作用,后面分析WindowManager的操作时会接触到。
目前为止,Window和View的大致概念和它们之间的关系交代完毕。
下面需要从WindowManager来继续探索界面框架的工作原理。
WindowManager
概念windowmanager表示用来管理操作Window的角色。
稍后会知道真实的动作完全是通过IPC调用系统服务WindowManagerService完成的,我们(调用api的客户端代码)接触到的是一个代理对象。
而WindowManager正是IPC的接口描述。
接口WindowManager继承了ViewManager,它的定义是:
/**InterfacetoletyouaddandremovechildviewstoanActivity.Togetaninstance
*ofthisclass,call{@linkandroid.content.Context#getSystemService(java.lang.String)Context.getSystemService()}.
*/
publicinterfaceViewManager{
//AssignthepassedLayoutParamstothepassedViewandaddtheviewtothewindow.
publicvoidaddView(Viewview,ViewGroup.LayoutParamsparams);
publicvoidupdateViewLayout(Viewview,ViewGroup.LayoutParamsparams);
publicvoidremoveView(Viewview);
}
上面的三个方法是面向Window的,分别用来添加,更新、和移除View。
Window是界面框架的基本单位,每个可视的独立交互的界面是一个Window,而界面可视元素是View组成的,View必须依附到Window来被最终绘制和显示。
SDK提供的界面又分为不同的Window类型,Dialog,StatusBar,Toast,Activity等,它们都是拥有View并依靠Window来显示内容的“界面类”。
ViewManager的这三个方法几乎就是WindowManager的所有职责,也是我们可以“间接”和Window打交道的方式。
addView时会创建新的Window并将传递的View作为其呈现的内容。
removeView时也就销毁了Window。
接口WindowManager继承ViewManager:
publicinterfaceWindowManagerextendsViewManager{
publicstaticclassLayoutParamsextendsViewGroup.LayoutParams
implementsParcelable{
//View的left,top
publicintx,y;
/**
*Thegeneraltypeofwindow.Therearethreemainclassesof
*windowtypes:
Applicationwindows、Systemwindows、Sub-windows。
*/
publicinttype;
//Variousbehavioraloptions/flags.
publicintflags;
//...
}
}
WindowManager.LayoutParams就是和Window中View相关的布局参数。
WindowManagerService
就像Activity的创建一样,Window的创建不是像View那样new出来的。
而是通过IPC调用系统服务WindowManagerService完成的。
如果接触过RemoteViews的话很容易明白类似的设计。
WindowManager的实现类是WindowManagerImpl:
/**
*Provideslow-levelcommunicationwiththesystemwindowmanagerfor
*operationsthatareboundtoaparticularcontext,displayorparentwindow.
*Instancesofthisobjectaresensitivetothecompatibilityinfoassociated
*withtherunningapplication.
*
*Thisobjectimplementsthe{@linkViewManager}interface,
*allowingyoutoaddanyViewsubclassasatop-levelwindowonthescreen.
*Additionalwindowmanagerspecificlayoutparametersaredefinedfor
*controloverhowwindowsaredisplayed.Italsoimplementsthe{@linkWindowManager}
*interface,allowingyoutocontrolthedisplaysattachedtothedevice.
*
*
ApplicationswillnotnormallyuseWindowManagerdirectly,insteadrelying
*onthehigher-levelfacilitiesin{@linkandroid.app.Activity}and
*{@linkandroid.app.Dialog}.
*
*
Evenforlow-levelwindowmanageraccess,itisalmostnevercorrecttouse
*thisclass.Forexample,{@linkandroid.app.Activity#getWindowManager}
*providesawindowmanagerforaddingwindowsthatareassociatedwiththat
*activity--thewindowmanagerwillnotnormallyall
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- android 界面 框架 Window