Window初步認(rèn)識

Window

該類是一個(gè)抽象類,提供了繪制窗口的一組通用API。

PhoneWindow

該類繼承于Window類,是Window類的具體實(shí)現(xiàn),即我們可以通過該類具體去繪制窗口。并且,該類內(nèi)部包含了 一個(gè)DecorView對象,該DectorView對象是所有應(yīng)用窗口(Activity界面)的根View。

DecorView

該類是一個(gè)FrameLayout的子類,并且是PhoneWindow的內(nèi)部變量,該類就是對普通的FrameLayout進(jìn)行功能的擴(kuò)展,更確切點(diǎn)可以說是修飾(Decor的英文全稱是Decoration,即“修飾”的意思),比如說添加TitleBar(標(biāo)題欄),以及TitleBar上的滾動條等 。最重要的一點(diǎn)是,它是所有應(yīng)用窗口的根View 。

包含ContentView和其他(StatusBar,ActionBar、ToolBar等)

ContentView

真正包含我們寫的Layout的父布局,是DecorView的一個(gè)子類,可以通過findViewById(com.android.internal.R.id.content)拿到該對象。

生成ContentView的源碼參考

//generateLayout
protected ViewGroup generateLayout(DecorView decor) {
  ...
    int layoutResource;
    int features = getLocalFeatures();
    // System.out.println("Features: 0x" + Integer.toHexString(features));
    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;
      }
      // XXX Remove this once action bar supports these features.
      removeFeature(FEATURE_ACTION_BAR);
      // System.out.println("Title Icons!");
    } else if ((features & ((1 << FEATURE_PROGRESS) | (1 << FEATURE_INDETERMINATE_PROGRESS))) != 0
               && (features & (1 << FEATURE_ACTION_BAR)) == 0) {
      // Special case for a window with only a progress bar (and title).
      // XXX Need to have a no-title version of embedded windows.
      layoutResource = R.layout.screen_progress;
      // System.out.println("Progress!");
    } else if ((features & (1 << FEATURE_CUSTOM_TITLE)) != 0) {
      // Special case for a window with a custom title.
      // If the window is floating, we need a dialog layout
      if (mIsFloating) {
        TypedValue res = new TypedValue();
        getContext().getTheme().resolveAttribute(
          R.attr.dialogCustomTitleDecorLayout, res, true);
        layoutResource = res.resourceId;
      } else {
        layoutResource = R.layout.screen_custom_title;
      }
      // XXX Remove this once action bar supports these features.
      removeFeature(FEATURE_ACTION_BAR);
    } else if ((features & (1 << FEATURE_NO_TITLE)) == 0) {
      // If no other features and not embedded, only need a title.
      // If the window is floating, we need a dialog layout
      if (mIsFloating) {
        TypedValue res = new TypedValue();
        getContext().getTheme().resolveAttribute(
          R.attr.dialogTitleDecorLayout, res, true);
        layoutResource = res.resourceId;
      } else if ((features & (1 << FEATURE_ACTION_BAR)) != 0) {
        layoutResource = a.getResourceId(
          R.styleable.Window_windowActionBarFullscreenDecorLayout,
          R.layout.screen_action_bar);
      } else {
        layoutResource = R.layout.screen_title;
      }
      // System.out.println("Title!");
    } else if ((features & (1 << FEATURE_ACTION_MODE_OVERLAY)) != 0) {
      layoutResource = R.layout.screen_simple_overlay_action_mode;
    } else {
      // Embedded, so no decoration is needed.
      layoutResource = R.layout.screen_simple;
      // System.out.println("Simple!");
    }

    mDecor.startChanging();
    mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);

    ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
    //ID_ANDROID_CONTENT = com.android.internal.R.id.conten
  ...
}

通過源碼會發(fā)現(xiàn)會根據(jù)設(shè)置主題的不同,ContentView的具體實(shí)現(xiàn)layout會不一樣!舉例說明screen_action_bar.xml(有actionBar)和screen_custom_title.xml(無actionBar)

  • screen_action_bar.xml
<com.android.internal.widget.ActionBarOverlayLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/decor_content_parent"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:splitMotionEvents="false"
    android:theme="?attr/actionBarTheme">
    <FrameLayout android:id="@android:id/content"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent" />
    <com.android.internal.widget.ActionBarContainer
        android:id="@+id/action_bar_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        style="?attr/actionBarStyle"
        android:transitionName="android:action_bar"
        android:touchscreenBlocksFocus="true"
        android:gravity="top">
        <com.android.internal.widget.ActionBarView
            android:id="@+id/action_bar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            style="?attr/actionBarStyle" />
        <com.android.internal.widget.ActionBarContextView
            android:id="@+id/action_context_bar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:visibility="gone"
            style="?attr/actionModeStyle" />
    </com.android.internal.widget.ActionBarContainer>
    <com.android.internal.widget.ActionBarContainer android:id="@+id/split_action_bar"
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  style="?attr/actionBarSplitStyle"
                  android:visibility="gone"
                  android:touchscreenBlocksFocus="true"
                  android:gravity="center"/>
</com.android.internal.widget.ActionBarOverlayLayout>
  • screen_custom_title.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:fitsSystemWindows="true">
    <!-- Popout bar for action modes -->
    <ViewStub android:id="@+id/action_mode_bar_stub"
              android:inflatedId="@+id/action_mode_bar"
              android:layout="@layout/action_mode_bar"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:theme="?attr/actionBarTheme" />

    <FrameLayout android:id="@android:id/title_container" 
        android:layout_width="match_parent" 
        android:layout_height="?android:attr/windowTitleSize"
        android:transitionName="android:title"
        style="?android:attr/windowTitleBackgroundStyle">
    </FrameLayout>
    <FrameLayout android:id="@android:id/content"
        android:layout_width="match_parent" 
        android:layout_height="0dip"
        android:layout_weight="1"
        android:foregroundGravity="fill_horizontal|top"
        android:foreground="?android:attr/windowContentOverlay" />
</LinearLayout>

setContentView()

Activity的setContetnView()最后會調(diào)用PhoneWindow的setContentView();


    @Override
    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)) {
            //如已經(jīng)存在,會將之前的View都全部移除掉,所以setContentView可以反復(fù)調(diào)用
            mContentParent.removeAllViews();
        }

        if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                    getContext());
            transitionTo(newScene);
        } else {
            mLayoutInflater.inflate(layoutResID, mContentParent);
        }
        mContentParent.requestApplyInsets();
        ...
    }

DectorView是在首次setContentView的時(shí)候才進(jìn)行初始化的

    private void installDecor() {
        mForceDecorInstall = false;
        if (mDecor == null) {
            mDecor = generateDecor(-1);
            mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
            mDecor.setIsRootNamespace(true);
            if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
                mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
            }
        } else {
            mDecor.setWindow(this);
        }
        if (mContentParent == null) {
            mContentParent = generateLayout(mDecor);
        }
        ...
    }

參考 http://blog.csdn.net/qinjuning/article/details/7226787

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容