Activity中setContentView浅析

Activity中setContentView浅析protectedvoidonCreate(finalBundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}setContentView()方法会将我们的视图设置到哪儿去了?publicvoidsetCo…

大家好,又见面了,我是你们的朋友全栈君。

protected void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
}

setContentView()方法会将我们的视图设置到哪儿去了?

public void setContentView(@LayoutRes int layoutResID) {
    getWindow().setContentView(layoutResID);
    initWindowDecorActionBar();
}

Activity会调用当前Activity的Window的setContentView()方法,而Window类是一个抽象类,唯一实现类PhoneWindow。

PhoneWindwo对象在Activity中的attach()方法中创建。

 final void attach(Context context, ActivityThread aThread,
        Instrumentation instr, IBinder token, int ident,
        Application application, Intent intent, ActivityInfo info,
        CharSequence title, Activity parent, String id,
        NonConfigurationInstances lastNonConfigurationInstances,
        Configuration config, String referrer, IVoiceInteractor voiceInteractor,
        Window window) {
    attachBaseContext(context);

    mFragments.attachHost(null /*parent*/);

    mWindow = new PhoneWindow(this, window);
    mWindow.setWindowControllerCallback(this);
    mWindow.setCallback(this);
    mWindow.setOnWindowDismissedCallback(this);
    mWindow.getLayoutInflater().setPrivateFactory(this);
    //......
}

那我们接着看PhoneWindow的setContentView()方法。

public void setContentView(int layoutResID) {

    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);
    }
    mContentParent.requestApplyInsets();
    final Callback cb = getCallback();
    if (cb != null && !isDestroyed()) {
        cb.onContentChanged();
    }
}

当我们第一此setContentView()时,mContentParent为空,会调用installDecor()方法做些初始化工作。然后再将我们setContentView里的View加载到mContentParent上面去。

mLayoutInflater.inflate(layoutResID, mContentParent)

来看看installDecor()做了什么伟大的事情:

private DecorView mDecor;

private ViewGroup mContentParent;

private ViewGroup mContentRoot;

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) {
        mContentParent = generateLayout(mDecor);

        // Set up decor part of UI to ignore fitsSystemWindows if appropriate.
        mDecor.makeOptionalFitsSystemWindows();
        //....
    }
}

mDecor是DecorView类对象,而DecorView继承自FrameLayout,generateDecor()方法就是初始化创建一个空的FrameLayout。来看generateLayout()方法是怎样初始化我们需要的mContentParent的:

protected ViewGroup generateLayout(DecorView decor) {   
    TypedArray a = getWindowStyle();
    if (a.getBoolean(R.styleable.Window_windowNoTitle, false)) {
        requestFeature(FEATURE_NO_TITLE);
    } else if (a.getBoolean(R.styleable.Window_windowActionBar, false)) {
        requestFeature(FEATURE_ACTION_BAR);
    }

    if (a.getBoolean(R.styleable.Window_windowActionBarOverlay, false)) {
        requestFeature(FEATURE_ACTION_BAR_OVERLAY);
    }
    //....
    if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
        layoutResource = R.layout.screen_swipe_dismiss;
    } else if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
        if (mIsFloating) {
            TypedValue res = new TypedValue();
            getContext().getTheme().resolveAttribute(
                    R.attr.dialogTitleIconsDecorLayout, res, true);
            layoutResource = res.resourceId;
        } else {
            layoutResource = 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 = R.layout.screen_progress;

    } else if ((features & (1 << FEATURE_CUSTOM_TITLE)) != 0) {}
    //.....
    int layoutResource;
    //.....
    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);
    //.....
    return contentParent;
 }

generateLayout()方法会根据我们Acivity主题样式,选择加载不同的系统布局资源,并将该视图添加到DecorView中去。

View in = mLayoutInflater.inflate(layoutResource, null);
decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
mContentRoot = (ViewGroup) in;

无论选择哪一个布局资源里面都一个id名为content的FrameLayout。再从该布局中找到我们需要的contentParent。

(ViewGroup)findViewById(ID_ANDROID_CONTENT);

最后返回contentParent,将setContentView()中的视图加载到mContentParent上去。
这里写图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/153245.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 母版页中ContentPlaceHolder 控件的作用

    母版页中ContentPlaceHolder 控件的作用文章转自http://wenku.baidu.com/link?url=7sLN0ihgZQ1XfX47b_y8qbpIVjS5T75Q1xvaoyIQ6OiKIgvzyVyRccnU9e9fqoOm4DBTxNyPPIpgGlq8n5l4cePZngx1J-va9PNFmdRn2se母版页中ContentPlaceHolder控件的作用。当母版页被一个页面引用时,页面内容…

    2022年7月13日
    18
  • Wappalyzer 是一个Firefox插件,也是一个网站

    Wappalyzer 是一个Firefox插件,也是一个网站https wappalyzer com download nbsp Wappalyzer 是一个 Firefox 插件 也是一个网站 安装 Firefox 插件后 它会检查每个网站使用了哪些 Web 应用程序 目前共 67 种 包括博客引擎 CMS 电子商务程序 统计工具 主机控制面板 Wiki 系统和 JS 框架等等 检查结果会以图片方式显示在 Firefox 浏览状态栏右侧

    2025年6月10日
    3
  • 电脑pin码忘了登录不进系统_做好这些优化,电脑5秒开机不是梦[通俗易懂]

    电脑pin码忘了登录不进系统_做好这些优化,电脑5秒开机不是梦[通俗易懂]为保证及时获取最新消息建议置顶公众号编辑:王富国审核:瓦彦文昨天公众号没有发文章,一是因为没有动力,毕竟写了文章没有回报,看不到任何的反馈,还有什么意思?二是因为我帮我一个朋友处理了一下她的电脑,也耗费了不少时间,也从中又得到了一些对电脑优化的经验,现在也给大家分享一下。本文较长,请耐心看完!昨天我这位朋友的电脑是全新的,对,刚买的,她自己看的,也是让我比较后,她自己选择购买的,配置大…

    2022年8月12日
    5
  • 19种电压转换的电路设计方式

    19种电压转换的电路设计方式标准三端线性稳压器的压差通常是2.0-3.0V。要把5V可靠地转换为3.3V,就不能使用它们。压差为几百个毫伏的低压降(LowDropout,LDO)稳压器,是此类应用的理想选择。图1-1是基本LDO系统的框图,标注了相应的电流。从图中可以看出,LDO由四个主要部分组成:技巧一:使用LDO稳压器,5V向3.3V系统供电标准三端线性稳压器的压差通常是2.0-3.0V。要把5V可靠地转换为3.3V,就不能使用它们。压差为几百个毫伏的低压降(LowD…

    2022年6月2日
    36
  • 锐捷交换机常用命令速查[通俗易懂]

    锐捷交换机常用命令速查[通俗易懂]准备工作       >Enable进入特权模式  #Exit  返回上一级操作模式  #End  返回到特权模式  #writememory或copyrunning-configstartup-config  保存配置文件  #delflash:config.text  删除配置文件(交换机及1700系列路由器)  #erasestartup-co

    2022年6月23日
    179
  • 人体表面积的计算公式_体表面积快速计算公式

    人体表面积的计算公式_体表面积快速计算公式体表面积(BSA)即是人体表面积。由于形状的特殊性,直接测量非常复杂。多年来,人们总结出许多计算公式用于估算体表面积。使用这些公式,身体表面积将以平方米计算出来。常用体表面积计算公式:1)Mosteller公式:一个最经常使用的公式,发布于1987年。BSA(m²)=([身高(cm)x体重(kg)]/3600)^½。2)DuBois与DuBois公式(1,注):BSA(…

    2022年4月19日
    485

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号