Android View 系統 1 - View樹
View簡介
在Android作業系統中,幾乎所有的UI元素都是基於View
和ViewGroup
建立出來的。View
就是一塊可以用來進行繪畫,可以處理輸入事件進行互動的矩形區域,而ViewGroup
就是一種可以容納View
的矩形容器。
下圖就是ViewGroup
和View
組成的UI佈局結構。View
和ViewGroup
通過這種樹形結構組合在一起,構成了我們在手機螢幕上看到的一個個的複雜的介面。
從設計模式的角度看,ViewGroup
和View
是組合模式的典型應用。View
是基本的控制元件元素,ViewManager
介面定義了新增、刪除View的介面addView、removeView
,ViewGroup
實現了ViewParent
的介面,因此可以作為容器管理View
,同時ViewGroup
又繼承自View
,可以被其他的ViewGroup
管理。這樣ViewGroup
和View
就可以組成上面的樹狀結構了。
實際的程式碼實現過程中很少會直接使用ViewGroup
和View
,而是使用繼承自它們的之類,如FrameLayout
、LinearLayout
、ListView
等是ViewGroup
的子類,TextView
、ImageView
、SurfaceView
等是View
的子類。
建立View樹
上面介紹了ViewGroup
和View
是通過View
樹的形式組合在一起的,一個View
樹也就是一個Layout
佈局,下面就介紹一下怎樣建立、管理Layout
佈局。
從Layout
資源建立View
樹
最常見的建立Layout
的方式就是使用Layout
資源。Android 應用的程式碼目錄結構裡,在資源res資料夾下有一個layout資料夾,應用中使用的layout資源都會放在這個資料夾下。父View與子View是以XML的形式巢狀在一起的,下面就是一個layout的例子:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<FrameLayout
android:id="@+id/container"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="I am a TextView" />
</FrameLayout>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="I am a Button" />
</LinearLayout>
同時layout之間也可以相互巢狀,如下面的形式:
<include layout="@layout/other_layout"/>
當在程式碼中需要使用XML資源裡定義的layout時可以使用下面的程式碼:
LayoutInflater inflater = getLayoutInflater();
View view = inflater.inflate(R.layout.main, null);
很多類中將通過LayoutInflater
載入資源的過程也封裝好了,只需要提供資源就可以了,如設定Activity
的ContentView
的程式碼:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
}
通過Layout
資源建立View
樹的優勢是層次結構清晰,管理方便。同時View
樹中各個View的屬性也可以在layout資源裡進行設定。缺點是無法在應用執行時對View樹結構進行變化。
從程式碼建立View樹
從Java程式碼中通過ViewGroup
的addView
、removeView
等介面同樣可以管理View樹,如下面的程式碼:
TextView text = new TextView(this);
Button button = new Button(this);
FrameLayout frame = new FrameLayout(this);
frame.addView(text);
LinearLayout linear = new LinearLayout(this);
linear.setOrientation(LinearLayout.VERTICAL);
linear.addView(frame);
linear.addView(button);
從程式碼中建立View樹最多的應用場景是在使用AdapterView
的子類的時候,如ListView、GridView、Spinner
等。繼承自AdapterView
的控制元件一般會通過一個介面卡Adapter來新增、刪除自己的子View
。
ListView list = new ListView(this);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, myStringArray);
list.setAdapter(adapter);
在程式碼中建立View
樹的優點是對View
的管理比較靈活,可以在程式執行過程中動態的管理View樹的狀態,缺點就是程式碼實現比較複雜,程式的擴充套件性不好不容易維護。
通常在開發過程中這兩種建立View
樹的方式是結合在一起使用的。
管理View
View
樹裡的每一個View
都會有一個整型ID,用來方便對這個View進行查詢管理,View
的ID可以在佈局檔案裡定義(如前面佈局資原始檔裡為TextView
指定的android:id="@+id/text"
)也可以在View例項建立後通過View.setId(int id)
方法設定。通過View樹中根節點的findViewById(int id)
方法就可以查詢到id對應的View。
LayoutInflater inflater = getLayoutInflater();
View view = inflater.inflate(R.layout.main, null);
TextView text = (TextView) view.findViewById(R.id.text);
View
樹中每個View的 ID 並不強制要求是唯一的,這樣可以方便一些子View樹重複利用(如ListView
中每個item的佈局),但是通過findViewById()
查詢時只會得到最先找到的View
,因此建議在資原始檔中定義的View
使用唯一的ID。
建立了view樹以後,還可能會根據實際場景對View
樹裡進行新增或者刪除View
的操作,使用前面提到過的addView、removeView
介面就可以,如:
LayoutInflater inflater = getLayoutInflater();
FrameLayout container = (FrameLayout) inflater.inflate(R.layout.main, null);
TextView text = (TextView) container.findViewById(R.id.text);
container.removeView(text);
Button button = new Button(this);
button.setId(button.hashCode());
container.addView(button);
相關文章
- Android技能樹 — View事件體系小結AndroidView事件
- View繪製01-Android渲染系統中的ViewViewAndroid
- Android技能樹 — View小結AndroidView
- Android View體系(4)AndroidView
- Android自定義View:View(二)AndroidView
- Android ViewAndroidView
- Android View 的事件體系AndroidView事件
- Android自定義view-自繪ViewAndroidView
- android自定義View——座標系AndroidView
- android view 分析AndroidView
- Android XML佈局報錯:android/view/View$OnUnhandledKeyEventListenerAndroidXMLView
- Techinical view on APO - 1View
- Android View post 方法AndroidView
- Android 自定義viewAndroidView
- Android: 自定義ViewAndroidView
- Android view架構AndroidView架構
- Android View總結AndroidView
- View 體系詳解:View 的工作流程View
- Android系統原始碼分析--View繪製流程之-inflateAndroid原始碼View
- Android自定義View基礎:座標系AndroidView
- 圖解Android - Android GUI 系統 (2) - 視窗管理 (View, Canvas, Window Manager)圖解AndroidGUIViewCanvas
- Android View 原始碼解析(三) – View的繪製過程AndroidView原始碼
- Android View 的工作原理AndroidView
- Android自定義View整合AndroidView
- Android新手引導ViewAndroidView
- Android View 使用總結AndroidView
- Android View繪製流程AndroidView
- android view background 問題AndroidView
- Android獲取view高度AndroidView
- Android系統原始碼分析--View繪製流程之-setContentViewAndroid原始碼View
- Android系統原始碼分析–View繪製流程之-setContentViewAndroid原始碼View
- 直播系統程式碼,Android自定義View實現呼吸燈效果AndroidView
- Android自定義View(1):對話方塊-DialogAndroidView
- Attempt to invoke virtual method ‘int android.view.View.getImportantForAccessibility()‘ on a null obAndroidViewImportNull
- Android繪製View的過程研究——計算View的大小AndroidView
- View的事件體系View事件
- [Android]關於Android子view超出父view無法響應點選事件AndroidView事件
- Android Touch事件傳遞機制全面解析(從WMS到View樹)Android事件View