转载请注明出处:http://blog.csdn.net/guxiao1201/article/details/41744107

首先贴出实现Activity对话框圆角的核心代码

  1. @Override
  2. public void onAttachedToWindow() {
  3. super.onAttachedToWindow();
  4. DisplayMetrics dm = new DisplayMetrics();
  5. getWindowManager().getDefaultDisplay().getMetrics(dm);
  6. View view = getWindow().getDecorView();
  7. WindowManager.LayoutParams lp = (WindowManager.LayoutParams)view.getLayoutParams();
  8. lp.gravity = Gravity.CENTER;
  9. lp.width = (dm.widthPixels * 4) / 5;
  10. lp.height = (dm.widthPixels * 4) / 5;
  11. getWindowManager().updateViewLayout(view,lp);
  12. getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
  13. view.setBackgroundResource(R.drawable.dialog_activity_bg);
  14. }

在上篇博客onAttachedToWindow()在整个Activity生命周期的位置及使用中解释了为什么在onAttachedToWindow中修改窗口尺寸,上面代码最后两行分别对window和decorView设置背景,那么问题来了,一个窗体中decorView和window之间的关系是什么?

通过文章开始贴出的代码View view = getWindow().getDecorView();就可以对Window和DecorView的层级关键猜测一二,decorView是否作为一个变量由window维护?
和之前思路一样,想探究这个问题就得看源码说话。这里依然参考老罗的博客Android应用程序窗口(Activity)的视图对象(View)的创建过程分析

既然猜测decorView是window的变量,那么就先找到window和activity之间的关系。通过源码发现

  1. public class Activity extends ContextThemeWrapper
  2. implements LayoutInflater.Factory,
  3. Window.Callback, KeyEvent.Callback,
  4. OnCreateContextMenuListener, ComponentCallbacks {
  5. ......
  6. private Window mWindow;
  7. ......
  8. public Window getWindow() {
  9. return mWindow;
  10. }
  11. ......
  12. public void setContentView(int layoutResID) {
  13. getWindow().setContentView(layoutResID);
  14. }
  15. ......
  16. }

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一探究竟。

  1. public class PhoneWindow extends Window implements MenuBuilder.Callback {
  2. ......
  3. // This is the top-level view of the window, containing the window decor.
  4. private DecorView mDecor;
  5. ......
  6. // This is the view in which the window contents are placed. It is either
  7. // mDecor itself, or a child of mDecor where the contents go.
  8. private ViewGroup mContentParent;
  9. ......
  10. private TextView mTitleView;
  11. ......
  12. private CharSequence mTitle = null;
  13. ......
  14. private void installDecor() {
  15. if (mDecor == null) {
  16. mDecor = generateDecor();
  17. ......
  18. }
  19. if (mContentParent == null) {
  20. mContentParent = generateLayout(mDecor);
  21. mTitleView = (TextView)findViewById(com.android.internal.R.id.title);
  22. if (mTitleView != null) {
  23. if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) {
  24. View titleContainer = findViewById(com.android.internal.R.id.title_container);
  25. if (titleContainer != null) {
  26. titleContainer.setVisibility(View.GONE);
  27. } else {
  28. mTitleView.setVisibility(View.GONE);
  29. }
  30. if (mContentParent instanceof FrameLayout) {
  31. ((FrameLayout)mContentParent).setForeground(null);
  32. }
  33. } else {
  34. mTitleView.setText(mTitle);
  35. }
  36. }
  37. }
  38. }
  39. ......
  40. }

在这里总算找到了DecorView,和上面猜测的一样,DecorView确实为Window的变量。同时还发现一个名为mContentParent的ViewGroup,那么这个变量的作用是什么?和DecorView有什么关系?带着问题接着往下看。

PhoneWindow的setContentView方法

  1. @Override
  2. public void setContentView(int layoutResID) {
  3. if (mContentParent == null) {
  4. installDecor();
  5. } else {
  6. mContentParent.removeAllViews();
  7. }
  8. mLayoutInflater.inflate(layoutResID, mContentParent);
  9. final Callback cb = getCallback();
  10. if (cb != null && !isDestroyed()) {
  11. cb.onContentChanged();
  12. }
  13. }

在mContentParent为null时会调用installDecor()来创建应用程序窗口视图对象。接着在installDecor()中调用generateLayout为mContentParent赋值。

  1. protected ViewGroup generateLayout(DecorView decor) {
  2. // 获取<Activity android:theme=""/>中的theme属性或者代码requestWindowFeature()中指定的Features
  3. TypedArray a = getWindowStyle();
  4. if (false) {
  5. System.out.println("From style:");
  6. String s = "Attrs:";
  7. for (int i = 0; i < com.android.internal.R.styleable.Window.length; i++) {
  8. s = s + " " + Integer.toHexString(com.android.internal.R.styleable.Window[i]) + "="
  9. + a.getString(i);
  10. }
  11. System.out.println(s);
  12. }
  13. mIsFloating = a.getBoolean(com.android.internal.R.styleable.Window_windowIsFloating, false);
  14. int flagsToUpdate = (FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR)
  15. & (~getForcedWindowFlags());
  16. if (mIsFloating) {
  17. setLayout(WRAP_CONTENT, WRAP_CONTENT);
  18. setFlags(0, flagsToUpdate);
  19. } else {
  20. setFlags(FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR, flagsToUpdate);
  21. }
  22. //...
  23. // Inflate the window decor.
  24. int layoutResource;
  25. int features = getLocalFeatures();
  26. // System.out.println("Features: 0x" + Integer.toHexString(features));
  27. if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
  28. if (mIsFloating) {
  29. TypedValue res = new TypedValue();
  30. getContext().getTheme().resolveAttribute(
  31. com.android.internal.R.attr.dialogTitleIconsDecorLayout, res, true);
  32. layoutResource = res.resourceId;
  33. } else {
  34. layoutResource = com.android.internal.R.layout.screen_title_icons;
  35. }
  36. // XXX Remove this once action bar supports these features.
  37. removeFeature(FEATURE_ACTION_BAR);
  38. // System.out.println("Title Icons!");
  39. } else if ((features & ((1 << FEATURE_PROGRESS) | (1 << FEATURE_INDETERMINATE_PROGRESS))) != 0
  40. && (features & (1 << FEATURE_ACTION_BAR)) == 0) {
  41. // Special case for a window with only a progress bar (and title).
  42. // XXX Need to have a no-title version of embedded windows.
  43. layoutResource = com.android.internal.R.layout.screen_progress;
  44. // System.out.println("Progress!");
  45. } else if ((features & (1 << FEATURE_CUSTOM_TITLE)) != 0) {
  46. // Special case for a window with a custom title.
  47. // If the window is floating, we need a dialog layout
  48. if (mIsFloating) {
  49. TypedValue res = new TypedValue();
  50. getContext().getTheme().resolveAttribute(
  51. com.android.internal.R.attr.dialogCustomTitleDecorLayout, res, true);
  52. layoutResource = res.resourceId;
  53. } else {
  54. layoutResource = com.android.internal.R.layout.screen_custom_title;
  55. }
  56. // XXX Remove this once action bar supports these features.
  57. removeFeature(FEATURE_ACTION_BAR);
  58. } else if ((features & (1 << FEATURE_NO_TITLE)) == 0) {
  59. // If no other features and not embedded, only need a title.
  60. // If the window is floating, we need a dialog layout
  61. if (mIsFloating) {
  62. TypedValue res = new TypedValue();
  63. getContext().getTheme().resolveAttribute(
  64. com.android.internal.R.attr.dialogTitleDecorLayout, res, true);
  65. layoutResource = res.resourceId;
  66. } else if ((features & (1 << FEATURE_ACTION_BAR)) != 0) {
  67. layoutResource = com.android.internal.R.layout.screen_action_bar;
  68. } else {
  69. layoutResource = com.android.internal.R.layout.screen_title;
  70. }
  71. // System.out.println("Title!");
  72. } else if ((features & (1 << FEATURE_ACTION_MODE_OVERLAY)) != 0) {
  73. layoutResource = com.android.internal.R.layout.screen_simple_overlay_action_mode;
  74. } else {
  75. // Embedded, so no decoration is needed.
  76. layoutResource = com.android.internal.R.layout.screen_simple;
  77. // System.out.println("Simple!");
  78. }
  79. mDecor.startChanging();
  80. View in = mLayoutInflater.inflate(layoutResource, null);
  81. decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
  82. ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
  83. if (contentParent == null) {
  84. throw new RuntimeException("Window couldn't find content container view");
  85. }
  86. if ((features & (1 << FEATURE_INDETERMINATE_PROGRESS)) != 0) {
  87. ProgressBar progress = getCircularProgressBar(false);
  88. if (progress != null) {
  89. progress.setIndeterminate(true);
  90. }
  91. }
  92. // Remaining setup -- of background and title -- that only applies
  93. // to top-level windows.
  94. if (getContainer() == null) {
  95. Drawable drawable = mBackgroundDrawable;
  96. if (mBackgroundResource != 0) {
  97. drawable = getContext().getResources().getDrawable(mBackgroundResource);
  98. }
  99. mDecor.setWindowBackground(drawable);
  100. drawable = null;
  101. if (mFrameResource != 0) {
  102. drawable = getContext().getResources().getDrawable(mFrameResource);
  103. }
  104. mDecor.setWindowFrame(drawable);
  105. // System.out.println("Text=" + Integer.toHexString(mTextColor) +
  106. // " Sel=" + Integer.toHexString(mTextSelectedColor) +
  107. // " Title=" + Integer.toHexString(mTitleColor));
  108. if (mTitleColor == 0) {
  109. mTitleColor = mTextColor;
  110. }
  111. if (mTitle != null) {
  112. setTitle(mTitle);
  113. }
  114. setTitleColor(mTitleColor);
  115. }
  116. mDecor.finishChanging();
  117. return contentParent;
  118. }

上面代码可看到将一些页面特性布局,例如ActionBar、Title等添加到decorView中,并且根据代码ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);可看到原来mContentParent是id="@android:id/content"的ViewGroup。再回到PhoneWindow.setContentView

  1. mLayoutInflater.inflate(layoutResID, mContentParent);

原来我们自定义的View都是mContentParent的子View。并且上面这段代码还发现了为什么必须在setContentView之前才能执行requestWindowFeature的彩蛋。

根据上面所有的猜测和分析,最终发现Window、DecorView和mContentParent的层级关系如下图(如有误请指正)

参考资料:

Window窗口布局--DecorView浅析

Android应用程序窗口(Activity)的视图对象(View)的创建过程分析

from:http://blog.csdn.net/guxiao1201/article/details/41744107

【转】decorView和window之间的层级及关系的更多相关文章

  1. 简析Window、Activity、DecorView以及ViewRoot之间的错综关系

    一.职能简介 Activity Activity并不负责视图控制,它只是控制生命周期和处理事件.真正控制视图的是Window.一个Activity包含了一个Window,Window才是真正代表一个窗 ...

  2. window之间、iframe之间的JS通信

    一.Window之间JS通信 在开发项目过程中,由于要引入第三方在线编辑器,所以需要另外一个窗口(window),而且要求打开的window要与原来的窗口进行js通信,那么如何实现呢? 1.在原窗口创 ...

  3. UML类图画法及其之间的几种关系(转)

    UML类图画法及其之间的几种关系 最近做重构项目,需要画一下类图,发现类图的画法及其之间的几种关系已经淡忘了很多,所以整理总结一下,有问题的地方大家可以一起讨论下. 文章目录如下: 类图画法 类之间的 ...

  4. Spring Framework------>version4.3.5.RELAESE----->Reference Documentation学习心得----->使用spring framework的IoC容器功能----->方法一:使用XML文件定义beans之间的依赖注入关系

    XML-based configuration metadata(使用XML文件定义beans之间的依赖注入关系) 第一部分 编程思路概述 step1,在XML文件中定义各个bean之间的依赖关系. ...

  5. UML类图画法及其之间的几种关系

    最近做重构项目,需要画一下类图,发现类图的画法及其之间的几种关系已经淡忘了很多,所以整理总结一下,有问题的地方大家可以一起讨论下. 文章目录如下: 类图画法 类之间的几种关系:泛化(Generaliz ...

  6. Hibernate基于注解方式配置来实现实体和数据库之间存在某种映射关系

    实体和数据库之间存在某种映射关系,hibernate根据这种映射关系完成数据的存取.在程序中这种映射关系由映射文件(*.hbm.xml)或者java注解(@)定义. 本文以java注解的形式总结映射关 ...

  7. C++:基类与派生类对象之间的赋值兼容关系

    4.5 基类与派生类对象之间的赋值兼容关系 在一定条件下,不同类型的数据之间可以进行类型转换,例如可以将整型数据赋给双精度型变量. 在赋值之前,先把整型数据转换为双精度型数据,然后再把它双精度型变量. ...

  8. 图解UML类与类之间的六中关系

    大话设计模式上的一个图,我用EA画出来的:  UML中的6大关系相关英文及音标:  依赖关系 dependency [di'pendənsi]  关联关系 association  [ə,səuʃi' ...

  9. jmeter断言:断言条件之间是“或”的关系

    有时,我们在做断言时,需要同时满足一系列条件,这在jmeter自带响应断言中已经实现: 有时,同一请求在不同时间,返回的响应是不同的,而这都是正确的响应,也就是说,我们判断的条件之间是或的关系,此时, ...

随机推荐

  1. Service生命周期以及应用

    Service概念及用途: Android中的服务,它与Activity不同,它是不能与用户交互的,不能自己启动的,运行在后台的程序,如果我们退出应用时,Service进程并没有结束,它仍然在后台运行 ...

  2. Es创建索引、设置和修改Mapping

    Http接口操作示例如下: 1.创建索引: 2.删除索引: 3.创建mapping: 4.查看mapping:

  3. SpringMVC+MyBatis+MySQL 8小时链接断开

    org.springframework.web.util.NestedServletException: Request processing failed; nested exception is ...

  4. hihocoder 1485----hiho字符串

    hihocoder 1485:hiho字符串 描述 如果一个字符串恰好包含2个'h'.1个'i'和1个'o',我们就称这个字符串是hiho字符串. 例如"oihateher".&q ...

  5. 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 ...

  6. oracle 企业管理器及无线网环境下配置方法

    注意: oracle em 的访问地址在 D:\oracle\product\11.2.0\dbhome_1\install 下的文件里. 如果在windows 安装oracle,并且在本地访问,or ...

  7. mysql 客户端

    MySQL是基于C/S模式的数据库管理系统.MySQL公司开发了众多的客户端软件来帮助用户管理MySQL软件,最著名的就是 MySQL Command Line Client 和 MySQL-Work ...

  8. Pig的使用场景

    数据转换加载(ETL)数据流:读取原始数据(比如用户日志),进行数据清洗,进行简单的预计算后导入到数据仓库,比如join连接数据库里的用户信息.

  9. ExtJs 4.1.1 文件结构解析

  10. 滑动cell的时候执行动画效果

    滑动cell的时候执行动画效果 效果图: 源码: // // ViewController.m // AniTab // // Created by XianMingYou on 15/2/26. / ...