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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • mac idea jrebel 激活

    mac idea jrebel 激活jrebel 官网提供注册 然后会给你一个注册码首先 idea 安装 jrebel 在安装完成之后 点击以下按钮一开始跟我的不一样 我的是注册完成之后 才会显示 Changelicens 的这个提示 之前好像是 Activatenow 提示 点击即可当注册完成之后 关闭弹出框选择上图中的值 去官网注册 https zeroturnarou com

    2026年1月16日
    16
  • 面试springbean的生命周期_session生命周期面试

    面试springbean的生命周期_session生命周期面试笑了

    2026年1月23日
    3
  • 字符串数组转换为list集合

    字符串数组转换为list集合String[]arr={“a”,”C”,”abc”}; //asList该方法可以直接将一个数组转换为list集合,但是该集合是[只读的],不能对得到的集合进行增删改List<String>asList=Arrays.asList(arr);System.out.println(asList);//结果:[a,C,abc]Listlis…

    2022年6月21日
    35
  • Manjaro Linux安装Termius

    Manjaro Linux安装Termius可以看到官网实际上提供每个 Linux 环境的安装方法 需要哪个版本自己去找就好了 我这里以 ManjaroLinux 为例子 Installtermi apponManjaro Snapcrafthtt snapcraft io install termius app manjaroInsta apponLinux SnapStoreGet

    2025年11月26日
    5
  • CACL联赛第一赛季第一轮比赛排名公布!

    CACL联赛第一赛季第一轮比赛排名公布!亲爱的同学们,CACL联赛第一赛季第一轮,“波士顿房价预测”比赛结束啦!本轮比赛共计31支队伍提交了有效结果。一、比赛结果第一名:浙江大学AI俱乐部第二名:中国海洋大学智能数据分析俱乐部第三名:重庆邮电大学人工智能协会恭喜同学们获得好名次,也非常感谢同学们的热情参与。排名前五的结果代码已在T-CCP社区公布。点击查看>>>另外排名前五的战队会颁发获奖证书,第六名及以后…

    2025年6月26日
    2
  • STM32 的 “位带”操作Bit-banding–学习笔记

    STM32 的 “位带”操作Bit-banding–学习笔记利用2个32MB大小的“虚拟”内存空间实现对2个1MB大小的物理内存空间进行“位”的置位和清除操作。这样就可以有效地对设备寄存器和位于SRAM中的数据变量进行位操作,而不再需要冗长的布尔逻辑运算过程。…

    2022年9月25日
    6

发表回复

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

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