Window窗口布局 --- DecorView淺析
開發中,通常都是在onCreate()中呼叫setContentView(R.layout.custom_layout)來實現想要的頁面佈局,我們知道,頁面都是依附在視窗之上的,而DecorView即是視窗最頂層的檢視。Android frameworks中,與視窗檢視處理相關的類,主要是Window及其實現類PhoneWindow
public class PhoneWindow extends Window implements MenuBuilder.Callback {
//...
//視窗頂層View private DecorView mDecor;
//所有自定義View的根View, id="@android:id/content"private ViewGroup mContentParent;
DecorView其實是PhoneWindow中的一個內部類,本質上也是一個View,其只是擴充套件了FrameLayout的實現
private final class DecorView extends FrameLayout implements RootViewSurfaceTaker { //...
頁面layout被新增至視窗Window的流程大致如下:
1,Activity中呼叫setContentView(R.layout.custom_layout), 具體實現為PhoneWindow中的同名方法
public void setContentView(int layoutResID) {
//getWindow()獲取的即是PhoneWindow物件
getWindow().setContentView(layoutResID); }
2, PhoneWindow執行setContentView(int layoutResource)
public void setContentView(int layoutResID) {
//初始,mContentParent為空 if (mContentParent == null) { installDecor();} else { mContentParent.removeAllViews(); }
//inflate自定義layout, 並將mContentParent作為其根檢視 mLayoutInflater.inflate(layoutResID, mContentParent);
3, PhoneWindow.installDecor()
private void installDecor() { if (mDecor == null) {
//new一個DecorView mDecor = generateDecor(); mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS); mDecor.setIsRootNamespace(true); if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) { mDecor.postOnAnimation(mInvalidatePanelMenuRunnable); } } if (mContentParent == null) {
//這一步會設定視窗的修飾檔案,並將id為ID_ANDROID_CONTENT的view find出來作為返回值賦值給mContentParent mContentParent = generateLayout(mDecor);
4, PhoneWindow.generateLayout(DecorView decor)
protected ViewGroup generateLayout(DecorView decor) { //4.1,獲取<Application android:theme=""/>, <Activity/>節點指定的themes或者程式碼requestWindowFeature()中指定的Features, 並設定 TypedArray a = getWindowStyle(); //... //4.2,獲取視窗Features, 設定相應的修飾佈局檔案,這些xml檔案位於frameworks/base/core/res/res/layout下 int layoutResource; int features = getLocalFeatures(); if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) { if (mIsFloating) { TypedValue res = new TypedValue(); getContext().getTheme().resolveAttribute(com.android.internal.R.attr.dialogTitleIconsDecorLayout, res, true); layoutResource = res.resourceId; } else { layoutResource = com.android.internal.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 = com.android.internal.R.layout.screen_progress; //...
mDecor.startChanging(); //4.3, 將上面選定的佈局檔案inflate為View樹,新增到decorView中 View in = mLayoutInflater.inflate(layoutResource, null); decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)); //將視窗修飾佈局檔案中id="@android:id/content"的View賦值給mContentParent, 後續自定義的view/layout都將是其子View ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT); if (contentParent == null) { throw new RuntimeException("Window couldn't find content container view"); }
//...
從上述步驟中,可以看出為什麼在程式碼中必須要在setContentView(...)之前才能執行requestWindowFeature(...)
5, 最後頁面中設定的自定義layout會被新增到mContentParent中
mLayoutInflater.inflate(layoutResID, mContentParent);
所以,Window視窗的佈局層次結構(features不同,可能標題欄不存在, 這種情況下,視窗修飾檢視區域與mContentParent內容區域重疊)如下所示:
示例:
Activity程式碼:
@Override protected void onCreate(Bundle savedInstanceState) { //設定視窗無標題欄 requestWindowFeature(Window.FEATURE_NO_TITLE); super.onCreate(savedInstanceState); setContentView(R.layout.activity_decor); }
activity_decor.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".DecorActivity"> <TextView android:text="@string/hello_world" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:text="@string/hello_world" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true"/> </RelativeLayout>
onCreate()中設定的Window.FEATURE_NO_TITLE對應的視窗修飾佈局檔案為screen_simple.xml, 原始碼如下,
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" android:orientation="vertical"> <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" /> <FrameLayout android:id="@android:id/content" android:layout_width="match_parent" android:layout_height="match_parent" android:foregroundInsidePadding="false" android:foregroundGravity="fill_horizontal|top" android:foreground="?android:attr/windowContentOverlay" /> </LinearLayout>
原始碼中id為"@android:id/content"的FrameLayout就是內容區域,在整個流程中,其會賦值給PhoneWindow類中的屬性mContentParent, 執行應用後,使用SDK提供的hierarchyviewer工具檢視頁面的ViewTree結構,可以看到結構如下:
相關推薦
Window窗口布局 --- DecorView淺析
開發中,通常都是在onCreate()中呼叫setContentView(R.layout.custom_layout)來實現想要的頁面佈局,我們知道,頁面都是依附在視窗之上的,而DecorView即是視窗最頂層的檢視。Android frameworks中,與視窗檢視處理相關的類,主要是Window及其實現
05 用xml檔案視覺化設計窗口布局
前面一直用程式碼來設計視窗的佈局,每次修改後,只有程式執行時才可看到設計的結果,而且當視窗的控制元件較多時,寫程式碼的方式較為麻煩了。 所以Android裡還提供了用xml檔案,用視覺化的方式來設計窗口布局. 首先還是先用嚮導建立一個”Add No Act
VC6 窗口布局恢復
vc 6.0中的小控制元件不小心點沒有,右鍵下圖中紅筆圈中的地方,勾選相應的控制元件就好了。 如果workspace視窗不能鎖定在視窗的左側時可以試試下面的這個命令。 vc 6.0中有do
Qt實戰--主窗口布局
QMainWindow MainWindow類我們一般選擇直接繼承自QMainWindow,因為QMainWindow已經向我們提供了一個常用的應用程式主窗口布局,包括QMenuBar選單欄、QToolBar工具欄、QStatusBar狀態列、QDo
QT5(5)窗口布局
程式碼自行補充標頭檔案 一、分割視窗QSplitter 在新建專案時不選建立視窗,在main.cpp中修改為: #include "mainwindow.h" #include <QApplication> #include <QSp
vs2012窗口布局恢復
我的環境。WIN7系統,使用的VS2012 問題出現在系統藍屏後,VS2012窗口布局出現問題,並不是我以前的佈局,點選視窗選單選擇重置窗口布局也不起作用。 解決方法:點選工具選單--匯入和匯出設定 有3個選項 。匯入,匯出,和重置。 選擇重置,VS2012會儲存你當前的配
Qt Creator窗口布局
使用Qt Creator對視窗進行佈局,相對於使用C++程式碼佈局而言,直觀快速,是首選的方法。本文重點在於敘述使用Qt Creator對視窗進行佈局的一些技巧。 1 Layouts 在Qt Creator左側的控制元件列表中,有4種佈局控制元件,而在其上方
pyqt4 基本視窗,窗口布局,設定logo,視窗最大最小化
#-*- coding:utf-8 -*- ####上面一行是指定編碼,這樣檔案中(包括註釋)才能使用中文,否則無法執行 #pyqt4基本視窗示例 from PyQt4.QtCore import * from PyQt4.QtGui import * import sys
MATLAB之simulink與command window窗口交互
image simulink http sim log 技術分享 logs blog cnblogs simulink中scope數據傳輸到command window窗口中 再完善!!!MATLAB之simulink與command window窗口交互
emWin 2天速成實例教程003_Framewin和Window窗口控件和2D繪圖
emwin framewin window 控件 窗體 備註:(1)打開工程目錄下的"Exe\GUISimulationDebug.exe"即可看到效果。(2)看完教程000~005就基本會用emWin做項目,其他章節可以需要時再參考。(1) emWin的每個界面都需要
javascript獲取window窗口常用函數
javascript獲取window窗口獲取窗口滾動條高度: /******************** *獲取窗口滾動條高度 ******************/ function getScrollTop() { var scrollTop=0; if(document.documentElement&
通過C# WinForm控件創建的WPF WIndow窗口控件無法輸入的問題
一次 開始 info keyboard 輸入法 .dll enable board 非模態 原文:通過WinForm控件創建的WPF 控件無法輸入的問題 今天把寫的一個WPF程序發布到別的機器上執行,發現一個比較奇怪的問題:在那個機器上用英文輸入法無法輸入數字,非要切換到
Window窗口
遊戲 pri iou console 技術分享 window hiera 服務 兼容 Window 窗口 Next Window:下一個窗口 Previous Window:前一個窗口 Layouts:布局 Unity Services:統一的服務 Scene:場景 Ga
恢復VS2013窗口的默認布局
href jpg index -o tex f2c http wrap self 打開VS2013 在菜單欄中找到“Window”即“窗口”選項
QMdiArea及QMdiSubWindow實現父子窗口及布局方法
light reat htm god cti www 圖片 des tac 版權聲明:若無來源註明,Techie亮博客文章均為原創。 轉載請以鏈接形式標明本文標題和地址: 本文標題:QMdiArea及QMdiSubWindow實現父子窗口及布局方法 本文地址:ht
Win32API全局窗口類的註冊與創建
zcl icon 全局 class border 字符 rbac 標題 def Win32API全局窗口類的註冊 應用程序全局窗口類的註冊 typedef struct tagWNDCLASSEX { UINT cbSize; //
洛谷P1886 滑動窗口(POJ.2823 Sliding Window)(區間最值)
最大 ide dma include names target org void blog To 洛谷.1886 滑動窗口 To POJ.2823 Sliding Window 題目描述 現在有一堆數字共N個數字(N<=10^6),以及一個大小為k的窗口。現在這個
關於window.open窗口的resize事件
ren enter itl 窗口 query 參考手冊 cti cnblogs span jQuery 事件 - resize() 方法 當調整瀏覽器窗口的大小時,發生 resize 事件。 resize() 方法觸發 resize 事件,或規定當發生 resize 事件時
[Leetcode] minimum window substring 最小字符窗口
為什麽 目的 -s pan 遍歷 uno 一個 tro you Given a string S and a string T, find the minimum window in S which will contain all the characters in T
WPF window 子窗口反饋效果(拉動/漸變)
nbsp Owner oar == boa ado 每次 value cti 當子窗口顯示後,點擊子窗口外部,需要有反饋動畫。 實現: 1.事件捕捉 每次點擊子窗口外部,即母窗口時,事件捕捉如下 HwndSource hwndSource = PresentationSo