Window窗口布局 --- DecorView浅析
开发中,通常都是在onCreate()中调用setContentView(R.layout.custom_layout)来实现想要的页面布局,我们知道,页面都是依附在窗口之上的,而DecorView即是窗口最顶层的视图。Android frameworks中,与窗口视图处理相关的类,主要是Window及其实现类PhoneWindow
public class PhoneWindow extends Window implements MenuBuilder.Callback {
//... //窗口顶层View
private DecorView mDecor;
//所有自定义View的根View, id="@android:id/content"
private ViewGroup mContentParent;
DecorView其实是PhoneWindow中的一个内部类,本质上也是一个View,其只是扩展了FrameLayout的实现
private final class DecorView extends FrameLayout implements RootViewSurfaceTaker { //...
页面layout被添加至窗口Window的流程大致如下:
1,Activity中调用setContentView(R.layout.custom_layout), 具体实现为PhoneWindow中的同名方法
public void setContentView(int layoutResID) {
//getWindow()获取的即是PhoneWindow对象
getWindow().setContentView(layoutResID);
}
2, PhoneWindow执行setContentView(int layoutResource)
public void setContentView(int layoutResID) {
//初始,mContentParent为空
if (mContentParent == null) {
installDecor();
} else {
mContentParent.removeAllViews();
}
//inflate自定义layout, 并将mContentParent作为其根视图
mLayoutInflater.inflate(layoutResID, mContentParent);
3, PhoneWindow.installDecor()
private void installDecor() {
if (mDecor == null) {
//new一个DecorView
mDecor = generateDecor();
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(true);
if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
}
}
if (mContentParent == null) {
//这一步会设置窗口的修饰文件,并将id为ID_ANDROID_CONTENT的view find出来作为返回值赋值给mContentParent
mContentParent = generateLayout(mDecor);
4, PhoneWindow.generateLayout(DecorView decor)
protected ViewGroup generateLayout(DecorView decor) {
//4.1,获取<Application android:theme=""/>, <Activity/>节点指定的themes或者代码requestWindowFeature()中指定的Features, 并设置
TypedArray a = getWindowStyle();
//...
//4.2,获取窗口Features, 设置相应的修饰布局文件,这些xml文件位于frameworks/base/core/res/res/layout下
int layoutResource;
int features = getLocalFeatures();
if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
if (mIsFloating) {
TypedValue res = new TypedValue();
getContext().getTheme().resolveAttribute(com.android.internal.R.attr.dialogTitleIconsDecorLayout, res, true);
layoutResource = res.resourceId;
} else {
layoutResource = com.android.internal.R.layout.screen_title_icons;
}
removeFeature(FEATURE_ACTION_BAR);
} else if ((features & ((1 << FEATURE_PROGRESS) | (1 << FEATURE_INDETERMINATE_PROGRESS))) != 0 && (features & (1 << FEATURE_ACTION_BAR)) == 0) {
layoutResource = com.android.internal.R.layout.screen_progress;
//...
mDecor.startChanging();
//4.3, 将上面选定的布局文件inflate为View树,添加到decorView中
View in = mLayoutInflater.inflate(layoutResource, null);
decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
//将窗口修饰布局文件中id="@android:id/content"的View赋值给mContentParent, 后续自定义的view/layout都将是其子View
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
if (contentParent == null) {
throw new RuntimeException("Window couldn't find content container view");
}
//...
从上述步骤中,可以看出为什么在代码中必须要在setContentView(...)之前才能执行requestWindowFeature(...)
5, 最后页面中设置的自定义layout会被添加到mContentParent中
mLayoutInflater.inflate(layoutResID, mContentParent);
所以,Window窗口的布局层次结构(features不同,可能标题栏不存在, 这种情况下,窗口修饰视图区域与mContentParent内容区域重叠)如下所示:
示例:
Activity代码:
@Override
protected void onCreate(Bundle savedInstanceState) {
//设置窗口无标题栏
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_decor);
}
activity_decor.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".DecorActivity"> <TextView
android:text="@string/hello_world"
android:layout_width="wrap_content"
android:layout_height="wrap_content" /> <TextView
android:text="@string/hello_world"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"/> </RelativeLayout>
onCreate()中设置的Window.FEATURE_NO_TITLE对应的窗口修饰布局文件为screen_simple.xml, 源码如下,
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical">
<ViewStub android:id="@+id/action_mode_bar_stub"
android:inflatedId="@+id/action_mode_bar"
android:layout="@layout/action_mode_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<FrameLayout
android:id="@android:id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foregroundInsidePadding="false"
android:foregroundGravity="fill_horizontal|top"
android:foreground="?android:attr/windowContentOverlay" />
</LinearLayout>
源码中id为"@android:id/content"的FrameLayout就是内容区域,在整个流程中,其会赋值给PhoneWindow类中的属性mContentParent, 运行应用后,使用SDK提供的hierarchyviewer工具查看页面的ViewTree结构,可以看到结构如下:
参考资料:
http://blog.csdn.net/qinjuning/article/details/7226787
http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.4.2_r1/android/view/Window.java?av=f
http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.4.2_r1/com/android/internal/policy/impl/PhoneWindow.java?av=f
http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.4.2_r1/frameworks/base/core/res/res/layout/screen_simple.xml?av=f
http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.4.2_r1/android/app/Activity.java?av=f
Window窗口布局 --- DecorView浅析的更多相关文章
- [转载]ExtJs4 笔记(9) Ext.Panel 面板控件、 Ext.window.Window 窗口控件、 Ext.container.Viewport 布局控件
作者:李盼(Lipan)出处:[Lipan] (http://www.cnblogs.com/lipan/)版权声明:本文的版权归作者与博客园共有.转载时须注明本文的详细链接,否则作者将保留追究其法律 ...
- ExtJs4 笔记(9) Ext.Panel 面板控件、 Ext.window.Window 窗口控件、 Ext.container.Viewport 布局控件
本篇讲解三个容器类控件. 一.面板控件 Ext.Panel 一个面板控件包括几个部分,有标题栏.工具栏.正文.按钮区.标题栏位于最上面,工具栏可以在四个位置放置,围绕中间部分正文,按钮区位于最小方.下 ...
- 窗口-EasyUI Window 窗口、EasyUI Dialog 对话框、EasyUI Messager 消息框
EasyUI Window 窗口 扩展自 $.fn.panel.defaults.通过 $.fn.window.defaults 重写默认的 defaults. 窗口(window)是一个浮动的.可拖 ...
- (四)EasyUI 使用——form表单2 & window窗口
form表单组件主要有以下内容(如下图) 6. progressbar进度条 每隔1秒让进度条按随机数填充,直至充满进度条刻度(只能执行一次) 进度条: <div id=" ...
- 第二百零三节,jQuery EasyUI,Window(窗口)组件
jQuery EasyUI,Window(窗口)组件 学习要点: 1.加载方式 2.属性列表 3.事件列表 4.方法列表 本节课重点了解 EasyUI 中 Window(窗口)组件的使用方法,这个组件 ...
- 保持plsql窗口布局
在window菜单中有个 save layout 项,设置好窗口布局后,选一下此项就保存你当前的窗口布局了,下次启动就不用再设置了.
- EasyUI笔记(三)Window窗口
本系列只列出一些常用的属性.事件或方法,具体完整知识请查看API文档 Window(窗口) 窗口控件是一个浮动和可拖拽的面板可以用作应用程序窗口.默认情况下,窗口可以移动,调整大小和关闭.它的内容也可 ...
- IDEA的窗口布局设置
修改idea的窗口布局 idea默认的窗口模式是如: 可以通过File->Appearance->Window Options->勾选 Widescreen tool window ...
- JavaScript:window窗口对象
在JavaScript中,window表示的就是一个窗口对象.所以在整个处理过程之中,所有的操作都是以弹框为主 的.范例1:使用警告框 <script type="text/javas ...
随机推荐
- MySQL---2、安装与部署
1.MySQL下载 MySQL版本的选择MySQL Community Server 社区版本,开源免费,但不提供官方技术支持.MySQL Enterprise Edition 企业版本,需付费,可以 ...
- 关于C#委托和Lambda表达式
关于C#委托和Lambda表达式 1.C#委托和Lambda表达式结合定义方法非常方便 在定一次性方法有很好的应用 delegate void getProductNoReturn(int a); d ...
- tensorboard实现tensorflow可视化
1.工程目录 2.data.input_data.py的导入 在tensorflow更新之后可以进行直接的input_data的导入 # from tensorflow.examples.tutori ...
- CSS(一)sytle
一:CSS语法组成: 选择符 和声明(声明和声明之间用分号隔开) 声明部分:属性和属性值(用冒号链接) 语法:选择符{ 属性1:属性值: 属性2:属性值: } 所有的CSS语句都要放到 ...
- [COCI2006-2007#1] Bond
状压DP \(dp[i]\)表示当前选人状态为\(i\)且选择了前\(i.count()\)个物品时最大的概率 #include"cstdio" #include"cst ...
- 洛谷P3939 数颜色(二分 vector)
题意 题目链接 Sol 直接拿vector维护每种颜色的出现位置,然后二分一下. #include<bits/stdc++.h> using namespace std; const in ...
- 常用SEO优化
- Shellinabox安装及使用教程
本文转载自: shellinabox:一款使用 AJAX 的基于 Web 的终端模拟器 一.shellinabox简介 通常情况下,我们在访问任何远程服务器时,会使用常见的通信工具如OpenSSH和P ...
- java中的==、equals()、hashCode()源码分析(转载)
在java编程或者面试中经常会遇到 == .equals()的比较.自己看了看源码,结合实际的编程总结一下. 1. == java中的==是比较两个对象在JVM中的地址.比较好理解.看下面的代码: ...
- 安装使用jupyter
介绍 jupyter是IPython剥离出来成为一个语言无关的独立软件包. jupyter已经支持50多种语言的内核,包括Lisp.R.F#.Perl.Ruby.Scala等.事实上即使IPython ...