android View和ViewGroup如何在应用程序界面(窗口)中显示

转载 2016年08月31日 16:05:59

参考 http://blog.csdn.net/yanbober/article/details/45970721

参考 上一篇LayoutInflater的学习

我们平时从手机上看到的一个界面,他们其实就是一系列的View对象由树状的形式组合成的View对象树视图。这些View对象被新建出来后,他们会根据自己的绘制规则将自己绘制成视图形式,绘制完毕后由Activity线程将他们整体显示出来。(看完文章后的理解,纯粹为了理解,并没检验正假。。。。反正只有自己看)。下面以及参考链接主要讲的是我们这个View对象树的结构,以及形成原理。


先说结构

看见上面图没?Activity中有一个成员为Window,其实例化对象为PhoneWindow,PhoneWindow为抽象Window类的实现类。

这里先简要说明下这些类的职责:

  1. Window是一个抽象类,提供了绘制窗口的一组通用API。

  2. PhoneWindow是Window的具体继承实现类。而且该类内部包含了一个DecorView对象,该DectorView对象是所有应用窗口(Activity界面)的根View。

  3. DecorView是PhoneWindow的内部类,是FrameLayout的子类,是对FrameLayout进行功能的修饰(所以叫DecorXXX),是所有应用窗口的根View 。

就上面DectorView  PhoneWindow  Activity我自己的理解是,DectorView就好比是一个相框,PhoneWindow就是管理着相框的相册,而Activity就是拥有相册的主人(我们的相册比较高级,装的是相框),那么相片是什么?相片就是我们主要显示的内容,而将相片装载到相框里我们使用的是setContentView方法。

     详细的代码看参考的链接吧

      我们分析这种常用的这种类型的setContentView方法


    public void setContentView(int layoutResID) {
        // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window
        // decor, when theme attributes and the like are crystalized. Do not check the feature
        // before this happens.
        if (mContentParent == null) {
            installDecor();
        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            mContentParent.removeAllViews();
        }

        if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                    getContext());
            transitionTo(newScene);
        } else {
            mLayoutInflater.inflate(layoutResID, mContentParent);
        }
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
            cb.onContentChanged();
        }
    }
方法一开始就有这段代码
if (mContentParent == null) {
            installDecor();}

mContentParent是什么?它是一个容纳我们layoutID对应View或ViewGroup的容器ViewGroup,一开始它当然为空,然后我们执行installDector();

 private void installDecor() {
        if (mDecor == null) {
            mDecor = generateDecor();
            mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
            mDecor.setIsRootNamespace(true);
            if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
                mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
            }
        }
        if (mContentParent == null) {
            //根据窗口的风格修饰,选择对应的修饰布局文件,并且将id为content的FrameLayout赋值给mContentParent
            mContentParent = generateLayout(mDecor);
            //......
            //初始化一堆属性值
        }
    }

 一开始mDecor = generateDecor()仅仅是初始化一个的ViewDecor对象。

然后看方法

mContentParent = generateLayout(mDecor);

protected ViewGroup generateLayout(DecorView decor) {
        // Apply data from current theme.

        TypedArray a = getWindowStyle();

        //......
        //依据主题style设置一堆值进行设置

        // Inflate the window decor.

        int layoutResource;
        int features = getLocalFeatures();
        //......
        //根据设定好的features值选择不同的窗口修饰布局文件,得到layoutResource值

        //把选中的窗口修饰布局文件添加到DecorView对象里,并且指定contentParent值
        View in = mLayoutInflater.inflate(layoutResource, null);
        decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
        mContentRoot = (ViewGroup) in;

        ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
        if (contentParent == null) {
            throw new RuntimeException("Window couldn't find content container view");
        }

        //......
        //继续一堆属性设置,完事返回contentParent
        return contentParent;
    }

首先根据features的值设置layoutResoutce的值,代码中省略这一步,然后View in = mLayoutInflater.inflate(layoutResource, null);生成相应的View

接着mdecor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));将in这个View添加到mdecor.

ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);在mdecor中找到ID为ID_ANDROID_CONTENT这个布局设置为contentParent,并将其返回个mContentParent

mContentRoot = (ViewGroup) in;这个就是我们layoutResource对应的View,它也是contentParent的父容器。

回到setContentView方法

mLayoutInflater.inflate(layoutResID, mContentParent);将我们加载的页面添加到mContentParent。

所以为什么我们layoutResID对应布局的layout_....属性得到正常显示,以为我们使用的是mLayoutInflater.inflate(layoutResID, mContentParent);

最后总的层次结构

phoneWindow--ViewDecor--mRootContent--mContentParent--我们自己的布局文件









Android自定义ViewGroup添加组合控件的子view

自定义ViewGroup添加组合控件的子view时 一定要重写 @Override protected void onMeasure(int widthMeasureSpec, int hei...
  • zahuopuboss
  • zahuopuboss
  • 2016年01月20日 16:38
  • 1124

Android自定义ViewGroup ,动态添加数目不确定的ImageView

开发中遇到这样的需求,在页面中显示数量不确定的图片。如果不用自定义ViewGroup的话,只能在layout中一个一个的添加ImageView。这样做显然是不合适的,而且会有相当多的重复代码。面对这样...
  • qq_20801369
  • qq_20801369
  • 2017年10月24日 19:52
  • 191

Android中View和ViewGroup的详细解释:

Android中View和ViewGroup的详细解释1. 概述: Android系统中的所有UI类都是建立在View和ViewGroup这两个类的基础上的。所有View的子类成为”Wi...
  • u014225510
  • u014225510
  • 2015年05月23日 19:10
  • 1274

Android ViewGroup和View的传递事件

最近项目中遇到了几种自定义View的覆盖使用,导致事件传递混了,查到了相关资料,最后自己做一个总结,留作记忆 http://blog.csdn.net/yanzi1225627/article/det...
  • gyh790005156
  • gyh790005156
  • 2015年08月06日 14:30
  • 1105

深入理解view和viewgroup以及安卓屏幕图层基础

概述: Android系统中的所有UI类都是建立在View和ViewGroup这两个类的基础上的。所有View的子类成为”Widget”,所有ViewGroup的子类成为”Layout”。Vi...
  • qq_37237245
  • qq_37237245
  • 2017年04月28日 16:40
  • 416

android自定义viewGroup 不显示问题

欢迎使用Markdown编辑器写博客本Markdown编辑器使用StackEdit修改而来,用它写博客,将会带来全新的体验哦: Markdown和扩展Markdown简洁的语法 代码块高亮 图片链接和...
  • qq493045049
  • qq493045049
  • 2016年05月23日 15:47
  • 554

Android ViewGroup 触摸事件传递机制

引言上一篇博客我们学习了Android View 触摸事件传递机制,不了解的同学可以查看Android View 触摸事件传递机制。今天继续学习Android触摸事件传递机制,这篇博客将和大家一起探讨...
  • feidu804677682
  • feidu804677682
  • 2015年08月01日 22:44
  • 3403

Android View系统分析之二View与ViewGroup

在Android View系统分析之从setContentView说开来(一)一文中,我们从setContentView开始阐述了Android中的视图层次,从设置内容布局到整个视图层次的建立的过程。...
  • bboyfeiyu
  • bboyfeiyu
  • 2014年10月04日 19:04
  • 5414

ViewGroup是如何加载布局中的view?

LayoutInflater如何加载布局?上面链接中的内容是此篇文章的基础,如果对LayoutInflater原理不熟悉可以去参考一下。1.问题由来本来在看CoordinatorLayout的源码,然...
  • javine
  • javine
  • 2016年12月14日 16:40
  • 1363

了解自定义View和继承View,继承ViewGroup,继承已有View,继承已有ViewGroup实例ji

自定义View的分类 继承View 当我们需要实现的效果是一个不规则效果的时候,那么这时就需要继承 View 来实现了,我们需要重写 onDraw 方法,在该方法里实现各种不规则的图形和效果。当我...
  • github_37217206
  • github_37217206
  • 2017年02月06日 10:25
  • 712
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:android View和ViewGroup如何在应用程序界面(窗口)中显示
举报原因:
原因补充:

(最多只允许输入30个字)