界面編程與視圖的組件
視圖組件與容器組件
Android應(yīng)用的絕大部分UI組件都放在android.widget包及其子包、android.view包及其子包中,Android應(yīng)用的所有UI組件都繼承了View類。
View類還有一個(gè)重要的子類:ViewGroup,但ViewGroup通常作為其他組件的容器使用。
Android的所有UI組件都是建立在View、ViewGroup基礎(chǔ)之上的,Android采用了“組合器”設(shè)計(jì)模式來設(shè)計(jì)View和ViewGroup:ViewGroup是View的子類,因此ViewGroup也可被當(dāng)成View使用。ViewGroup作為容器來盛裝其它組件,而ViewGroup里除了可以包含普通View組件之外,還可以再次包含ViewGroup組件。

Android推薦使用XML布局文件來定義用戶界面,而不是使用Java代碼來開發(fā)用戶界面,因此所有組件都提供了兩種方式來控制組件的行為:
- 在XML布局文件中通過XML屬性進(jìn)行控制
- 在Java程序代碼中通過調(diào)用方法進(jìn)行控制
# View類的XML屬性、相關(guān)方法及說明
| XML屬性 | 相關(guān)方法 | 說明 |
|---|---|---|
| android:alpha | setAlpha(float) | 設(shè)置該組件的透明度 |
| android:background | setBackgroundResource(int) | 設(shè)置該組件的背景顏色 |
| android:clickable | setClickable(boolean) | 設(shè)置該組件是否可以激發(fā)單擊事件 |
| android:contentDescription | setContentDescription(CharSequence) | 設(shè)置該組件的主要描述信息 |
| android:drawingCacheQuality | setDrawingCacheQuality(int) | 設(shè)置該組件所使用的繪制緩存的質(zhì)量 |
| android:fadeScrollbars | setScrollbarFadingEnabled(boolean) | 當(dāng)不使用該組件的滾動(dòng)條時(shí),是否淡出顯示滾動(dòng)條 |
| android:fadingEdge | setVerticalFadingEdgeEnabled(boolean) | 設(shè)置滾動(dòng)該組件時(shí)組件邊界是否使用淡出效果 |
| android:fadingEdgeLength | getVerticalFadingEdgeLength() | 設(shè)置淡出邊界的長度 |
| android:focusable | setFocusable(boolean) | 設(shè)置該組件是否可以得到焦點(diǎn) |
| android:focusableInTouchMode | setFocusableInTouchMode(boolean) | 設(shè)置該組件在觸摸模式下是否可以得到焦點(diǎn) |
| android:id | setId(int) | 設(shè)置該組件的唯一標(biāo)識(shí),Java代碼中可通過findViewById來獲取它 |
| android:isScrollContainer | setScrollContainer(boolean) | 設(shè)置該組件是否是作為可滾動(dòng)容器使用 |
| android:nextFocusDown | setNextFocusDownId(int) | 設(shè)置焦點(diǎn)在該組件上,且按向下鍵時(shí)獲得焦點(diǎn)的組件ID |
| android:nextFocusLeft | setNextFocusLeftId(int) | 設(shè)置焦點(diǎn)在該組件上,且按向左鍵時(shí)獲得焦點(diǎn)的組件ID |
| android:nextFocusRight | setNextFocusRightID(int) | 設(shè)置焦點(diǎn)在該組件上,且按向右鍵時(shí)獲得焦點(diǎn)的組件ID |
| android:nextFocusUp | setNextFocusUpId(int) | 設(shè)置焦點(diǎn)在該組件上,且按向上鍵時(shí)獲得焦點(diǎn)的組件ID |
| android:onClick | 為該組件的單擊事件綁定監(jiān)聽器 | |
| android:padding | setPadding(int,int,int,int) | 在組件的四邊設(shè)置填充區(qū)域 |
| android:paddingBottom | setPadding(int,int,int,int) | 在組件的下邊設(shè)置填充區(qū)域 |
| android:paddingLeft | setPadding(int,int,int,int) | 在組件的左邊設(shè)置填充區(qū)域 |
| android:paddingRight | setPadding(int,int,int,int) | 在組件的右邊設(shè)置填充區(qū)域 |
| android:paddingTop | setPadding(int,int,int,int) | 在組件的上邊設(shè)置填充區(qū)域 |
| android:rotation | setRotation(float) | 設(shè)置該組件的旋轉(zhuǎn)角度 |
| android:rotationX | setRotationX(float) | 設(shè)置該組件繞X軸旋轉(zhuǎn)的角度 |
| android:rotationY | setRotationX(float) | 設(shè)置該組件繞Y軸旋轉(zhuǎn)的角度 |
| android:saveEnabled | setSaveEnabled(boolean) | 如果設(shè)置為false,那當(dāng)該組件被凍結(jié)時(shí)不會(huì)保存它的狀態(tài) |
| android:scaleX | setScaleX(float) | 設(shè)置該組件在水平方向的縮放比 |
| android:scaleY | setScaleY(float) | 設(shè)置該組件在垂直方向的縮放比 |
| android:scrollX | 該組件初始化后的水平滾動(dòng)偏移 | |
| android:scrollY | 該組件初始化后的垂直滾動(dòng)偏移 | |
| android:scrollbarAlwaysDrawHorizontalTrack | 設(shè)置該組件是否總是顯示水平滾動(dòng)條的軌道 | |
| android:scrollbarAlwaysDrawVerticalTrack | 設(shè)置該組件是否總是顯示垂直滾動(dòng)條的軌道 | |
| android:scrollbarDefaultDelayBeforeFade | setScrollBarDefaultDelayBeforeFade(int) | 設(shè)置滾動(dòng)條在淡出隱藏之前延遲多少毫秒 |
| android:scrollbarFadeDuration | setScrollBarFadeDuration(int) | 設(shè)置滾動(dòng)條淡出隱藏過程需要多少秒 |
| android:scrollbarSize | setScrollBarSize(int) | 設(shè)置垂直滾動(dòng)條的寬度和水平滾動(dòng)條的高度 |
| android:scrollbarStyle | setScrollBarStyle(int) | 設(shè)置滾動(dòng)條的風(fēng)格和位置,該屬性支持如下屬性值:insideOverlay, insideInset, outsideOverlay, outsideInset |
| android:scrollbarThumbHorizontal | 設(shè)置該組件的水平滾動(dòng)條的滑塊對(duì)應(yīng)的Drawable對(duì)象 | |
| android:scrollbarThumbVertical | 設(shè)置該組件的垂直滾動(dòng)條的滑塊對(duì)應(yīng)的Drawable對(duì)象 | |
| android:scrollbarTrackHorizontal | 設(shè)置該組件的水平滾動(dòng)條的軌道對(duì)應(yīng)的Drawable | |
| android:scrollbarTrackVertical | 設(shè)置該組件的垂直滾動(dòng)條的軌道對(duì)應(yīng)的Drawable | |
| android:scrollbars | 定義該組件滾動(dòng)時(shí)顯示幾個(gè)滾動(dòng)條。該屬性支持如下屬性值,none:不顯示滾動(dòng)條;horizontal:顯示水平滾動(dòng)條;vertical:顯示垂直滾動(dòng)條 | |
| android:soundEffectsEnabled | setSoundEffectsEnabled(boolean) | 設(shè)置該組件被單擊時(shí)是否使用音效 |
| android:tag | 為該組件設(shè)置一個(gè)字符串類型的tag值。接下來可通過View的getTag()獲取該字符串,或通過findViewWithTag()查找該組件 | |
| android:transformPivotX | setPivotX(float) | 設(shè)置該組件旋轉(zhuǎn)時(shí)旋轉(zhuǎn)中心的X坐標(biāo) |
| android:transformPivotY | setPivotY(float) | 設(shè)置該組件旋轉(zhuǎn)時(shí)旋轉(zhuǎn)中心的Y坐標(biāo) |
| android:translationX | setTranslationX(float) | 設(shè)置該組件在X方向上的位移 |
| android:translationY | setTranslationY(float) | 設(shè)置該組件在Y方向上的位移 |
| android:visibility | setVisibility(int) | 設(shè)置該組件是否可見 |
ViewGroup容器控制其子控件的分布依賴于ViewGroup.LayoutParams、ViewGroup.MarginLayoutParams兩個(gè)內(nèi)部類。
# ViewGroup.LayoutParams支持的兩個(gè)XML屬性
| XML屬性 | 說明 |
|---|---|
| android:layout_height | 指定該子組件的布局高度 |
| android:layout_width | 指定該子組件的布局寬度 |
android:layout_height和android:layout_width支持的屬性值:
-
match_parent:指定子組件的高度/寬度與父組件的高度/寬度相同 -
wrap_content:指定子組件的大小恰好能包裹它的內(nèi)容即可
# ViewGroup.MarginLayoutParams支持的屬性
XML屬性|相關(guān)方法|說明
---|---
android:layout_marginBottom|setMargins(int,int,int,int)|指定該子組件下邊的頁邊距
android:layout_marginLeft|setMargins(int,int,int,int)|指定該子組件左邊的頁邊距
android:layout_marginRight|setMargins(int,int,int,int)|指定該子組件右邊的頁邊距
android:layout_marginTop|setMargins(int,int,int,int)|指定該子組件上邊的頁邊距
使用XML布局文件控制UI界面
Android推薦使用XML布局文件來控制視圖,這樣不僅簡單、明了,而且可以將應(yīng)用的視圖控制邏輯從Java代碼中分離出來,放入XML文件中控制,從而更好地體現(xiàn)MVC原則。
在代碼中控制UI界面
雖然Android推薦使用XML布局文件來控制UI界面,但如果開發(fā)者愿意,Android允許開發(fā)者完全拋棄XML布局文件,完全在Java代碼中控制UI界面。
使用XML布局文件和Java代碼混合控制UI界面
完全使用Java代碼來控制UI界面不僅繁瑣,而且不利于解耦;而完全利用XML布局文件來控制UI界面雖然方便、便捷,但難免有失靈活。因此有時(shí)候,可能需要混合利用XML布局文件和代碼來控制UI界面。
當(dāng)混合使用XML布局文件和代碼來控制UI界面時(shí),習(xí)慣上把變化小、行為比較固定的組件放在XML布局文件中管理,而那些變化較多、行為控制比較復(fù)雜的組件則交給Java代碼來管理。
開發(fā)自定義View
當(dāng)Android系統(tǒng)提供的UI組件不足以滿足項(xiàng)目需要時(shí),開發(fā)者可以通過繼承View來派生自定義組件。
當(dāng)開發(fā)者打算派生自己的UI組件時(shí),首先定義一個(gè)繼承View基類的子類,然后重寫View類的一個(gè)或多個(gè)方法。
通??梢员挥脩糁貙懙姆椒ㄈ缦拢?/p>
| 方法名 | 說明 |
|---|---|
| 構(gòu)造器 | 重寫構(gòu)造器是定制View的最基本方式,當(dāng)Java代碼創(chuàng)建一個(gè)View實(shí)例,或根據(jù)XML布局文件加載并構(gòu)建界面時(shí)將需要調(diào)用該構(gòu)造器 |
| onFinishInflate() | 這是一個(gè)回調(diào)方法,當(dāng)應(yīng)用從XML布局文件加載該組件并利用它來構(gòu)建界面之后,該方法將會(huì)被回調(diào) |
| onMeasure(int,int) | 調(diào)用該方法來檢測View組件及它所包含的所有子組件的大小 |
| onLayout(boolean, int, int, int, int) | 當(dāng)該組件需要分配其子組件的位置、大小時(shí),該方法就會(huì)被回調(diào) |
| onSizeChanged(int,int,int,int) | 當(dāng)該組件的大小被改變時(shí)回調(diào)該方法 |
| onDraw(Canvas) | 當(dāng)該組件將要繪制它的內(nèi)容時(shí)回調(diào)該方法進(jìn)行繪制 |
| onKeyDown(int, KeyEvent) | 當(dāng)某個(gè)鍵被按下時(shí)觸發(fā)該方法 |
| onKeyUp(int, KeyEvent) | 當(dāng)松開某個(gè)鍵時(shí)觸發(fā)該方法 |
| onTrackballEvent(MotionEvent) | 當(dāng)發(fā)生軌跡球事件時(shí)觸發(fā)該方法 |
| onTouchEvent(MotionEvent) | 當(dāng)發(fā)生觸摸屏事件時(shí)觸發(fā)該方法 |
| onWindowFocusChanged(boolean) | 當(dāng)該組件得到、失去焦點(diǎn)時(shí)觸發(fā)該方法 |
| onAttachedToWindow() | 當(dāng)把該組件放入某個(gè)窗口時(shí)觸發(fā)該方法 |
| onDetachedFromWindow() | 當(dāng)把該組件從某個(gè)窗口上分離時(shí)觸發(fā)該方法 |
| onWindowVisibilityChanged(int) | 當(dāng)包含該組件的窗口的可見性發(fā)生改變時(shí)觸發(fā)該方法 |