最外層的佈局
最外層的View是Activity的mActivity.getWindow().getDecorView(),顯示爲PhoneWindow$DecorView
它的內部有FrameLayout爲id/content,通過FrameLayout frameLayout = (FrameLayout) mActivity.getWindow().getDecorView().findViewById(android.R.id.content);獲取到。
接下來獲取activity的LayoutInflater,通過LayoutInflater.from(mActivity)
然後利用inflate載入layout的xml。
LayoutInflater.from(mActivity).inflate(R.layout.custom_screen,frameLayout);
這樣把custom_screen.xml中的佈局內容加入爲frameLayout(即id/content)的子layout。
custom_screen.xml中的佈局
在custom_screen.xml中定義了2個並列級別的佈局:id/fullscreen_custom_content(FrameLayout),id/vertical_layout(LineraLayout)
其中id/fullscreen_custom_content中主要是佈局了NavScreen,而id/vertical_layout中主要佈局了WebView。
在id/vertical_layout中又定義了並列的兩個佈局:id/error_consol(LinearLayout),id/main_content(FrameLayout)
在BaseUi中成員變量:
FrameLayout mContentView;對應了id/main_content(FrameLayout)
FrameLayout mCustomViewContainer;對應了id/fullscreen_custom_content(FrameLayout),
LinearLayout mErrorConsoleContainer;對應了id/error_consol(LinearLayout)
TitleBar的佈局
接下來創建了一個TitleBar對象,TitleBar繼承自RelativeLayout,通過
LayoutInflater factory =LayoutInflater.from(context);
factory.inflate(R.layout.title_bar, this);
把title_bar.xml中的佈局加入到自己中。那麼看下title_bar.xml中定義的佈局
首先外層是一個id/titlebar(RelativeLayout),在id/titlebar內部又有id/taburlbar(NavigationBarPhone:NavigationBarBase: LinearLayout),id/snapshotbar_stub (ViewStub),id/autologin_stub (ViewStub),id/progress(PageProgressView:ImageView)
上述的四個佈局在TitleBar類中分別對應以下成員:
NavigationBarBase mNavBar;
SnapshotBar mSnapshotBar;
AutologinBar mAutoLogin;
private PageProgressView mProgress;
其中mSnapshotBar與mAutoLogin是通過inflateSnapshotBar()與inflateAutoLoginBar()函數動態加載出的。
NavigationBarPhone 佈局
NavigationBarPhone對應的佈局文件是title_bar_nav.xml
該文件中得到如下的佈局
由該佈局可見,很多ImageButton默認是不顯示的,只有需要時再顯示,即實際上幾個Image位於同樣的顯示位置,根據不同的狀態選擇顯示不同的ImageButton,比如在地址欄輸入url時,網站icon的id/iconcombo就不顯示。
經過了上述的描述。知道了TitleBar的佈局,但是TitleBar如何與之前的id/main_content
關聯上的呢?並且這裏還缺少了WebView這個核心控件。
回顧一下TitleBar是在BaseUi構造時創建的。而此時並沒有創建WebView。
在Controller:: createNewTab中創建了Tab並通過BaseUi::setActiveTab把WebView加入到佈局中。
Tab中WebView的佈局
Tab中有兩個主要的成員
// Main WebView wrapper
private View mContainer; //這個是WebView的外層的佈局view
// Main WebView
private WebView mMainView;
Tab的構造函數中會通過Tab::setWebView爲自身添加一個WebView控件。
Tab::setWebView會進一步調用Controller::onSetWebView,Controller::onSetWebView又會進一步調用BaseUi::onSetWebView,在BaseUi:: onSetWebView中會初始化Tab:: mContainer。
Tab:: mContainer對應了tab.xml中的佈局。該佈局中有個id/webview_wrapper(FrameLayout),Tab::mMainView會被設置給id/webview_wrapper(FrameLayout),作爲它的子View。
Tab的佈局如下:
id/main_content(FrameLayout)與Tab佈局與TitleBar佈局的關聯
至次,已經有了id/main_content(FrameLayout),又有了這個Tab佈局,還有一個TitleBar佈局。接下來是他們三個的連接。
在BaseUi::attachTabToContentView(Tab tab)中,會把Tab:: mContainer設置爲BaseUi::mContentView的子View,這樣id/main_content(FrameLayout)就與Tab佈局關聯上了。
在PhoneUi:: setActiveTab(final Tab tab)中,會調用WebView::setEmbeddedTitleBar,並把TitleBar對象作爲參數傳入。
WebView:: setEmbeddedTitleBar(View v),把TitleBar設置爲WebView的子View,這樣Tab佈局就與TitleBar佈局關聯上了。
這樣得到如下的佈局
多窗口頁面的佈局
上述是對於正常瀏覽網頁的佈局,接下來看下在多窗口頁面的佈局情況。當前打開了3個Tab,然後進入到多窗口頁面中。
回到最上面看下id/content(FrameLayout),它的一個子viewid/vertical_layout _content(LineraLayout) 即上述的瀏覽網頁時的佈局。另一個子viewid/fullscreen_custom_content(FrameLayout)則是顯示多窗口時的佈局。那麼接下來就看下顯示多窗口時,它旗下的佈局是怎樣的。
在BaseUi中id/fullscreen_custom_content(FrameLayout)對應成員protectedFrameLayout mCustomViewContainer;
在PhoneUi中會創建一個NavScreen(RelativeLayout)對象,並把它設置爲mCustomViewContainer的子view。NavScreen(RelativeLayout)對應的就是多窗口頁面的佈局。這樣就把多窗口頁面與id/fullscreen_custom_content(FrameLayout)關聯上了。
NavScreen的佈局
NavScreen本身繼承自RelativeLayout,其初始化時加載了nav_screen.xml佈局爲其子view。如下代碼
LayoutInflater.from(mContext).inflate(R.layout.nav_screen,this);
加載了nav_screen.xml中的佈局後如下
id/scroller(NavTabScroller)是多窗口圖片預覽的佈局。
NavTabScroller的佈局
NavTabScroller繼承自ScrollerView。其內部又創建了一個類ContentLayout,它是繼承自LinearLayout。NavTabScroller初始化時會創建ContentLayout並把ContentLayout設置爲它的子view。
ContentLayout根據屏幕的旋轉方向可以選擇水平或垂直佈局。
NavTabScroller中有成員BaseAdaptermAdapter;用於記錄添加進NavTabScroller:: ContentLayout中的子view的列表。
在NavScreen中會創建TabAdapter並把它設置給NavTabScroller。
TabAdapter中提供的View就是一個個的NavTabView,被TabAdapter組織起來,在把TabAdapter設置給NavTabScroller,NavTabScroller::ContentLayout會取出NavTabView並設置爲自己的子View。
NavTabView本身是集成自LinearLayout的。每個NavTabView對應一個Tab。由於NavTabScroller中管理了NavTabView,那麼也可以進一步的獲取到每個Tab的信息。這裏主要需要取出Tab的截圖以及網址信息等。
到了這裏可以看到多窗口頁面的圖片顯示區最外層輪廓是一個ScrollerView,這樣就可以滑動的看到裏面的一個個Tab的截圖了。
裏面是一個個的NavTabView。
NavTabView的佈局
NavTabView的初始化時會加載nav_tab_view.xml的佈局,並設置爲自身的子View。
LayoutInflater.from(mContext).inflate(R.layout.nav_tab_view,this);
加載後的佈局如下:
多窗口頁面整體佈局
綜合以上可得多窗口的整體佈局如下