【转】decorView和window之间的层级及关系
转载请注明出处:http://blog.csdn.net/guxiao1201/article/details/41744107
首先贴出实现Activity对话框圆角的核心代码
- @Override
- public void onAttachedToWindow() {
- super.onAttachedToWindow();
- DisplayMetrics dm = new DisplayMetrics();
- getWindowManager().getDefaultDisplay().getMetrics(dm);
- View view = getWindow().getDecorView();
- WindowManager.LayoutParams lp = (WindowManager.LayoutParams)view.getLayoutParams();
- lp.gravity = Gravity.CENTER;
- lp.width = (dm.widthPixels * 4) / 5;
- lp.height = (dm.widthPixels * 4) / 5;
- getWindowManager().updateViewLayout(view,lp);
- getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
- view.setBackgroundResource(R.drawable.dialog_activity_bg);
- }
在上篇博客onAttachedToWindow()在整个Activity生命周期的位置及使用中解释了为什么在onAttachedToWindow中修改窗口尺寸,上面代码最后两行分别对window和decorView设置背景,那么问题来了,一个窗体中decorView和window之间的关系是什么?
通过文章开始贴出的代码View view = getWindow().getDecorView();就可以对Window和DecorView的层级关键猜测一二,decorView是否作为一个变量由window维护?
和之前思路一样,想探究这个问题就得看源码说话。这里依然参考老罗的博客Android应用程序窗口(Activity)的视图对象(View)的创建过程分析。
既然猜测decorView是window的变量,那么就先找到window和activity之间的关系。通过源码发现
- public class Activity extends ContextThemeWrapper
- implements LayoutInflater.Factory,
- Window.Callback, KeyEvent.Callback,
- OnCreateContextMenuListener, ComponentCallbacks {
- ......
- private Window mWindow;
- ......
- public Window getWindow() {
- return mWindow;
- }
- ......
- public void setContentView(int layoutResID) {
- getWindow().setContentView(layoutResID);
- }
- ......
- }
Window原来是Activity的一个变量,可以通过getWindow()获取,而且Activity中经常用到的setContentView原来调用的是window的setContentView。那么Window是什么?在Activity中起什么作用?OK~带着问题再查阅Google的官方文档。
Abstract base class for a top-level window look and behavior policy. An instance of this class should be used as the top-level view added to the window manager. It provides standard UI policies such as a background, title area, default key processing, etc.
The only existing implementation of this abstract class is Android.policy.PhoneWindow, which you should instantiate when needing a Window. Eventually that class will be refactored and a factory method added for creating Window instances without knowing about a particular implementation.
Google说Window是WindowManager最顶层的视图,它负责背景(窗口背景)、Title之类的标准的UI元素,Window是一个抽象类,整个Android系统中PhoneWindow是Winodw的唯一实现类。所以接下来进入PhoneWinodw一探究竟。
- public class PhoneWindow extends Window implements MenuBuilder.Callback {
- ......
- // This is the top-level view of the window, containing the window decor.
- private DecorView mDecor;
- ......
- // This is the view in which the window contents are placed. It is either
- // mDecor itself, or a child of mDecor where the contents go.
- private ViewGroup mContentParent;
- ......
- private TextView mTitleView;
- ......
- private CharSequence mTitle = null;
- ......
- private void installDecor() {
- if (mDecor == null) {
- mDecor = generateDecor();
- ......
- }
- if (mContentParent == null) {
- mContentParent = generateLayout(mDecor);
- mTitleView = (TextView)findViewById(com.android.internal.R.id.title);
- if (mTitleView != null) {
- if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) {
- View titleContainer = findViewById(com.android.internal.R.id.title_container);
- if (titleContainer != null) {
- titleContainer.setVisibility(View.GONE);
- } else {
- mTitleView.setVisibility(View.GONE);
- }
- if (mContentParent instanceof FrameLayout) {
- ((FrameLayout)mContentParent).setForeground(null);
- }
- } else {
- mTitleView.setText(mTitle);
- }
- }
- }
- }
- ......
- }
在这里总算找到了DecorView,和上面猜测的一样,DecorView确实为Window的变量。同时还发现一个名为mContentParent的ViewGroup,那么这个变量的作用是什么?和DecorView有什么关系?带着问题接着往下看。
PhoneWindow的setContentView方法
- @Override
- public void setContentView(int layoutResID) {
- if (mContentParent == null) {
- installDecor();
- } else {
- mContentParent.removeAllViews();
- }
- mLayoutInflater.inflate(layoutResID, mContentParent);
- final Callback cb = getCallback();
- if (cb != null && !isDestroyed()) {
- cb.onContentChanged();
- }
- }
在mContentParent为null时会调用installDecor()来创建应用程序窗口视图对象。接着在installDecor()中调用generateLayout为mContentParent赋值。
- protected ViewGroup generateLayout(DecorView decor) {
- // 获取<Activity android:theme=""/>中的theme属性或者代码requestWindowFeature()中指定的Features
- TypedArray a = getWindowStyle();
- if (false) {
- System.out.println("From style:");
- String s = "Attrs:";
- for (int i = 0; i < com.android.internal.R.styleable.Window.length; i++) {
- s = s + " " + Integer.toHexString(com.android.internal.R.styleable.Window[i]) + "="
- + a.getString(i);
- }
- System.out.println(s);
- }
- mIsFloating = a.getBoolean(com.android.internal.R.styleable.Window_windowIsFloating, false);
- int flagsToUpdate = (FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR)
- & (~getForcedWindowFlags());
- if (mIsFloating) {
- setLayout(WRAP_CONTENT, WRAP_CONTENT);
- setFlags(0, flagsToUpdate);
- } else {
- setFlags(FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR, flagsToUpdate);
- }
- //...
- // Inflate the window decor.
- int layoutResource;
- int features = getLocalFeatures();
- // System.out.println("Features: 0x" + Integer.toHexString(features));
- 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;
- }
- // XXX Remove this once action bar supports these features.
- removeFeature(FEATURE_ACTION_BAR);
- // System.out.println("Title Icons!");
- } else if ((features & ((1 << FEATURE_PROGRESS) | (1 << FEATURE_INDETERMINATE_PROGRESS))) != 0
- && (features & (1 << FEATURE_ACTION_BAR)) == 0) {
- // Special case for a window with only a progress bar (and title).
- // XXX Need to have a no-title version of embedded windows.
- layoutResource = com.android.internal.R.layout.screen_progress;
- // System.out.println("Progress!");
- } else if ((features & (1 << FEATURE_CUSTOM_TITLE)) != 0) {
- // Special case for a window with a custom title.
- // If the window is floating, we need a dialog layout
- if (mIsFloating) {
- TypedValue res = new TypedValue();
- getContext().getTheme().resolveAttribute(
- com.android.internal.R.attr.dialogCustomTitleDecorLayout, res, true);
- layoutResource = res.resourceId;
- } else {
- layoutResource = com.android.internal.R.layout.screen_custom_title;
- }
- // XXX Remove this once action bar supports these features.
- removeFeature(FEATURE_ACTION_BAR);
- } else if ((features & (1 << FEATURE_NO_TITLE)) == 0) {
- // If no other features and not embedded, only need a title.
- // If the window is floating, we need a dialog layout
- if (mIsFloating) {
- TypedValue res = new TypedValue();
- getContext().getTheme().resolveAttribute(
- com.android.internal.R.attr.dialogTitleDecorLayout, res, true);
- layoutResource = res.resourceId;
- } else if ((features & (1 << FEATURE_ACTION_BAR)) != 0) {
- layoutResource = com.android.internal.R.layout.screen_action_bar;
- } else {
- layoutResource = com.android.internal.R.layout.screen_title;
- }
- // System.out.println("Title!");
- } else if ((features & (1 << FEATURE_ACTION_MODE_OVERLAY)) != 0) {
- layoutResource = com.android.internal.R.layout.screen_simple_overlay_action_mode;
- } else {
- // Embedded, so no decoration is needed.
- layoutResource = com.android.internal.R.layout.screen_simple;
- // System.out.println("Simple!");
- }
- mDecor.startChanging();
- View in = mLayoutInflater.inflate(layoutResource, null);
- decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
- ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
- if (contentParent == null) {
- throw new RuntimeException("Window couldn't find content container view");
- }
- if ((features & (1 << FEATURE_INDETERMINATE_PROGRESS)) != 0) {
- ProgressBar progress = getCircularProgressBar(false);
- if (progress != null) {
- progress.setIndeterminate(true);
- }
- }
- // Remaining setup -- of background and title -- that only applies
- // to top-level windows.
- if (getContainer() == null) {
- Drawable drawable = mBackgroundDrawable;
- if (mBackgroundResource != 0) {
- drawable = getContext().getResources().getDrawable(mBackgroundResource);
- }
- mDecor.setWindowBackground(drawable);
- drawable = null;
- if (mFrameResource != 0) {
- drawable = getContext().getResources().getDrawable(mFrameResource);
- }
- mDecor.setWindowFrame(drawable);
- // System.out.println("Text=" + Integer.toHexString(mTextColor) +
- // " Sel=" + Integer.toHexString(mTextSelectedColor) +
- // " Title=" + Integer.toHexString(mTitleColor));
- if (mTitleColor == 0) {
- mTitleColor = mTextColor;
- }
- if (mTitle != null) {
- setTitle(mTitle);
- }
- setTitleColor(mTitleColor);
- }
- mDecor.finishChanging();
- return contentParent;
- }
上面代码可看到将一些页面特性布局,例如ActionBar、Title等添加到decorView中,并且根据代码ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);可看到原来mContentParent是id="@android:id/content"的ViewGroup。再回到PhoneWindow.setContentView
- mLayoutInflater.inflate(layoutResID, mContentParent);
原来我们自定义的View都是mContentParent的子View。并且上面这段代码还发现了为什么必须在setContentView之前才能执行requestWindowFeature的彩蛋。
根据上面所有的猜测和分析,最终发现Window、DecorView和mContentParent的层级关系如下图(如有误请指正)
参考资料:
Android应用程序窗口(Activity)的视图对象(View)的创建过程分析
from:http://blog.csdn.net/guxiao1201/article/details/41744107
【转】decorView和window之间的层级及关系的更多相关文章
- 简析Window、Activity、DecorView以及ViewRoot之间的错综关系
一.职能简介 Activity Activity并不负责视图控制,它只是控制生命周期和处理事件.真正控制视图的是Window.一个Activity包含了一个Window,Window才是真正代表一个窗 ...
- window之间、iframe之间的JS通信
一.Window之间JS通信 在开发项目过程中,由于要引入第三方在线编辑器,所以需要另外一个窗口(window),而且要求打开的window要与原来的窗口进行js通信,那么如何实现呢? 1.在原窗口创 ...
- UML类图画法及其之间的几种关系(转)
UML类图画法及其之间的几种关系 最近做重构项目,需要画一下类图,发现类图的画法及其之间的几种关系已经淡忘了很多,所以整理总结一下,有问题的地方大家可以一起讨论下. 文章目录如下: 类图画法 类之间的 ...
- Spring Framework------>version4.3.5.RELAESE----->Reference Documentation学习心得----->使用spring framework的IoC容器功能----->方法一:使用XML文件定义beans之间的依赖注入关系
XML-based configuration metadata(使用XML文件定义beans之间的依赖注入关系) 第一部分 编程思路概述 step1,在XML文件中定义各个bean之间的依赖关系. ...
- UML类图画法及其之间的几种关系
最近做重构项目,需要画一下类图,发现类图的画法及其之间的几种关系已经淡忘了很多,所以整理总结一下,有问题的地方大家可以一起讨论下. 文章目录如下: 类图画法 类之间的几种关系:泛化(Generaliz ...
- Hibernate基于注解方式配置来实现实体和数据库之间存在某种映射关系
实体和数据库之间存在某种映射关系,hibernate根据这种映射关系完成数据的存取.在程序中这种映射关系由映射文件(*.hbm.xml)或者java注解(@)定义. 本文以java注解的形式总结映射关 ...
- C++:基类与派生类对象之间的赋值兼容关系
4.5 基类与派生类对象之间的赋值兼容关系 在一定条件下,不同类型的数据之间可以进行类型转换,例如可以将整型数据赋给双精度型变量. 在赋值之前,先把整型数据转换为双精度型数据,然后再把它双精度型变量. ...
- 图解UML类与类之间的六中关系
大话设计模式上的一个图,我用EA画出来的: UML中的6大关系相关英文及音标: 依赖关系 dependency [di'pendənsi] 关联关系 association [ə,səuʃi' ...
- jmeter断言:断言条件之间是“或”的关系
有时,我们在做断言时,需要同时满足一系列条件,这在jmeter自带响应断言中已经实现: 有时,同一请求在不同时间,返回的响应是不同的,而这都是正确的响应,也就是说,我们判断的条件之间是或的关系,此时, ...
随机推荐
- Service生命周期以及应用
Service概念及用途: Android中的服务,它与Activity不同,它是不能与用户交互的,不能自己启动的,运行在后台的程序,如果我们退出应用时,Service进程并没有结束,它仍然在后台运行 ...
- Es创建索引、设置和修改Mapping
Http接口操作示例如下: 1.创建索引: 2.删除索引: 3.创建mapping: 4.查看mapping:
- SpringMVC+MyBatis+MySQL 8小时链接断开
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is ...
- hihocoder 1485----hiho字符串
hihocoder 1485:hiho字符串 描述 如果一个字符串恰好包含2个'h'.1个'i'和1个'o',我们就称这个字符串是hiho字符串. 例如"oihateher".&q ...
- Difference between model.evaluate vs model.predict in Keras
The model.evaluate function predicts the output for the given input and then computes the metrics ...
- oracle 企业管理器及无线网环境下配置方法
注意: oracle em 的访问地址在 D:\oracle\product\11.2.0\dbhome_1\install 下的文件里. 如果在windows 安装oracle,并且在本地访问,or ...
- mysql 客户端
MySQL是基于C/S模式的数据库管理系统.MySQL公司开发了众多的客户端软件来帮助用户管理MySQL软件,最著名的就是 MySQL Command Line Client 和 MySQL-Work ...
- Pig的使用场景
数据转换加载(ETL)数据流:读取原始数据(比如用户日志),进行数据清洗,进行简单的预计算后导入到数据仓库,比如join连接数据库里的用户信息.
- ExtJs 4.1.1 文件结构解析
- 滑动cell的时候执行动画效果
滑动cell的时候执行动画效果 效果图: 源码: // // ViewController.m // AniTab // // Created by XianMingYou on 15/2/26. / ...