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开发之向应用程序界面绑定数据

在Android开发中常常需要通过界面控件来访问数据库,比如用获得数据库的值来填充表单,列表等。在这里我们使用数据适配器想空间绑定数据。    使用SimpleCursorAdapte绑定数据   比...

android的快捷方式——应用程序界面

1.系统应用程序界面 获取系统程序ApplicationInfo集合private void loadApplications(boolean isLaunching) { if (isLaunc...

Android与iPhone应用程序界面设计的差异性

elya妞和阿智分析时偏重于硬件和界面布局,问题普遍存在,有必要重新分析。分析问题前,先确认几个前提。Android的自身版本分裂严重,主要体现在屏幕分辨率多样化带来的界面适配问题、按键布局混杂和不同...

Android源码之“应用程序界面“分析一( 从settings开始)

Android源码之应用程序界面分析一(从settings开始): 一。 预热: 当我们点击"设置” ->“应用程序”中时,会出现应用程序的列表,而且,有“所有应用”,“已下载”如,“正在运行”等...

Android 应用程序界面设计建议

与 iOS 相比,Android 系统界面存在各种不协调,应用界面本身缺乏统一的规范。虽然 Android 的开放性为应用的自主发挥带来了最大的可能性,但如果系统本身能够提供标准的范例,也未必是一件坏...

Android和iPhone应用程序界面布局示例

下图是根据Android和iPhone这两个平台的“生产内容型的应用程序”整理出来的界面布局示例。所对比的4个点,均是两大平台的应用程序常规界面元素。    状态栏: Android...

Android源码之“应用程序界面“分析二(PackageManager和PackageManagerService)

上一篇中,我们用到了PackageManager的getPackageSizeInfo函数,来得到应用程序的详细信息,这一篇中,我们将深入PackageManager的内部,来一探究竟。

自己动手创建应用程序界面设计器

1、Demo界面及功能解释 2、Demo实现简述 3、参考资料 Demo下载 1、Demo界面及功能解释 编译并运行程序,界面如下: 图1: 图2: 功能概述:...

iPhone应用程序界面结构

1、iPhone应用程序的结构 iPhone应用程序的结构,可以分为以下四层,下面以下图所示的人人应用为例进行说明: 状态栏,主要用于展示电信运营商信息,信号强弱信息、...

智能家居:一种移动终端的投影应用程序界面的新功能-设计概要

一种移动终端的投影应用程序界面的新功能 二、所属技术领域 屏幕投影;屏幕共享;远程操作。 三、现有技术(背景技术) 未发现存在的技术或者应用,类似技术如下...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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