Android使用者介面開發概述
Android應用是運行於手機系統上的程式,這種程式給使用者的第一印象就是使用者介面。接下來從以下幾個方面來認識瞭解Android的介面UI元素。
1.1檢視元件View 在Android中View類是最基本的一個UI類,基本上所有的高階UI元件都是繼承View類實現的。Android應用的絕大部分UI元件都放在android.widget包及其子包、android.view包及其子包中,可以看到Android應用的所有UI元件都繼承了 View類。View類是Android系統平臺上使用者介面表示的基本單元,View的一些子類被統稱為Widgets (工具),提供了諸如文字輸入框和按鈕之類的UI物件的完整實現。
一個檢視(View)在螢幕上佔據了一塊矩形區域,它負責渲染這塊矩形區域(如將這塊矩形區域變成其他顏色),也可以處理這塊矩形區域發生的事件(如使用者單擊事件),並且可以設定這塊區域是否可見、是否可以獲取焦點等。
1.2檢視容器元件ViewGroup View類有一個非常重要的子類ViewGroup,其為View的一個擴充套件,可以容納多個 View,通過ViewGroup類可以建立有聯絡的子View組成的複合控制元件。
下圖表示Android圖形使用者介面的元件層次。 從上圖可以看出,多個檢視元件(View)可以存放在一個檢視容器(ViewGroup)中,該容器可以與其他檢視元件共同存放在另一個容器中,但是一個介面檔案中必須有且只有一個容器作為根結點。 Android的所有UI元件都是建立在View、ViewGroup基礎之上的,Android採用了 “組合器”設計模式來設計View和ViewGroup。對於一個Android應用的圖形使用者介面來說,ViewGroup作為容器來盛裝其他元件,而ViewGroup裡除了可以包含普通View元件之外,還可以再次包含ViewGroup元件。
1.3佈局元件Layout Android的介面元件比較多,為了更好的管理使用者介面裡的各元件,Android提供了佈局元件來進行管理。通過使用佈局元件,Android應用的圖形使用者介面具有良好的平臺無關性。
目前Android中主要有六種佈局,分別如下:
LinearLayout(線性佈局):
按照水平或垂直的順序將子元素(可以是控制元件或佈局)依次按照順序排列,每一個元素都位於前面一個元素之後。
RelativeLayout(相對佈局):
按照子元素之間的位置關係完成佈局的,作為Android系統五大布局中最靈活也是最常用的一種佈局方式,非常適合於一些比較複雜的介面設計。
TableLayout(表格佈局):
以行和列的形式對控制元件進行管理,每一行為一個TableRow物件,或一個View控制元件。
FrameLayout(幀佈局):
將所有的子元素放在整個介面的左上角,後面的子元素直接覆蓋前面的子元素。
AbsoluteLayout(絕對佈局):
將所有的子元素通過設定android:layout_x 和 android:layout_y屬性,將子元素的座標位置固定下來。
GridLayout(網格佈局):
是Android 4.0新增的佈局管理器,把整個容器劃分成為"行*列"個網格,每個網格可以放置一個元件,另外,也可以設定一個元件橫跨多個列和多個行。
以上幾種佈局類圖如下圖 所示:
關於佈局元件的內容,會在後續課程進行詳細學習,此處不做過多說明。
1.4佈局引數LayoutParams LayoutParams是用來設定檢視佈局的基類,基本的LayoutParams類只是用來描述檢視的寬度和高度。
Android提供的佈局類都是LayoutParams的子類,LayoutParams的子類主要有:
AbsListView.LayoutParams
AbsoluteLayout.LayoutParams
FrameLayout.LayoutParams
LinearLayout.LayoutParams
RadioGroup.LayoutParams
RelativeLayout.LayoutParams
TableLayout.LayoutParams
TableRow.LayoutParams
ViewGroup.MarginLayoutParams
WindowManager.LayoutParams
其中常用的是RelativeLayout.LayoutParams、LinearLayout.LayoutParams、ViewGroup.MarginLayoutParams。將會在後續內容中陸續學習,此處不在贅述。
二、UI介面通用屬性和方法
View類是所有UI元件的基類,其包含的XML屬性和方法是所有元件都可使用的,接下來一起先來整體學習,如下表所示。
XML屬性
相關方法
使用說明
android:alpha
setAlpha(float)
設定該元件的透明度
android:background
setBackgroundResource(int)
設定該元件的背景顏色
android:clickable
setClickable(boolean)
設定該元件是否可以激發單擊事件
android:contentDescription
setContentDescription(CharSequence)
設定該元件的內容描述資訊
android:drawingCacheQuality
setDrawingCacheQuality(int)
設定該元件所使用的繪製快取的質量
android:elevation
setElevation(float)
設定該元件“浮”起來的高度,通過設定該屬性可讓該元件呈現3D效果
android:fadeScrollbars
setScrollbarFadingEnabled(boolean)
當不使用該元件的滾動條時,是否淡出顯示滾動條
android:fadingEdge
setVerticalFadingEdgeEnabled(boolean)
設定滾動該元件時元件邊界是否使用淡出效果
android:fadingEdgeLength
getVerticalFadingEdgeLength()
設定淡出邊界的長度
android:focusable
setFocusable(boolean)
設定該元件是否可以得到焦點
android:focusablelnTouchMode
setFocusablelnTouchMode(boolean)
設定該元件在觸控模式下是否可以得到焦點
android:id
setld(int)
設定該元件的唯一標識。在java程式碼中可通過findViewById來獲取它
android:isScrollContainer
setScrollContainer(boolean)
設定該元件是否作為可滾動容器使用
android:keepScreenOn
setKeepScreenOn(boolean)
設定該元件是否會強制手機螢幕一直開啟
android:longCIickable
setLongClickable(boolean)
設定該元件是否可以響應長單擊事件
android:minHeight
setMinimumHeight(int)
設定該元件的最小高度
android:minWidth
etMinimumWidth(int)
設定該元件的最小寬度
android:nextFocusDown
setNextFocusDownld(int)
設定焦點在該元件上,且單擊向下鍵時獲得焦點的元件ID
android:nextFocusLeft
setNextFocusLefUd(int)
設定焦點在該元件上,且單擊向左鍵時獲得焦點的元件ID
android:nextFocusRight
setNextFocusRightld(int)
設定焦點在該元件上,且單擊向右鍵時獲得焦點的元件ID
androidrnextFocusUp
setNexlFocusUpId(int)
設定焦點在該元件上,且單擊向上鍵時獲得焦點的元件ID
android.onClick
為該元件的單擊事件繫結監聽器
android:padding
setPadding(int,int,int,int)
在元件的四邊設定填充區域
android:paddingBottom
setPadding(int,int,int,int)
在元件的下邊設定填充區域
android:paddingLeft
setPadding(int,int,int,int)
在元件的左邊設定填充區域
android:paddingRight
setPadding(int,int,int,int)
在元件的右邊設定填充區域
android:paddingTop
setPadding(int,int,int,int)
在元件的上邊設罝填充區域
android:rotation
setRotation(float)
設定該元件旋轉的角度
android:rotationX
setRotationX(float)
設定該元件繞Xi軸旋轉的角度
android:rotationY
setRotationY(float)
設定該元件繞Y軸旋轉的角度
android:saveEnabled
setSaveEnabled(boolean)
如果設定為false,那麼當該元件被凍結時不會儲存它的狀態
android:scaleX
setScaleX(float)
設定該元件在水平方向的縮放比
android:scaleY
setScaleY(float)
設定該元件在垂直方向的縮放比
android:scrollX
該元件初始化後的水平滾動偏移
android:scrollY
該元件初始化後的垂直滾動偏移
android:scrollbarAlwaysDrawHorizontalTrack
設定該元件是否總是顯示水平滾動條的軌道
android:scrollbarAlwaysDrawVerticalTrack
設定該元件是否總是顯示垂直滾動條的軌道
android:scrollbarDefaultDelayBeforeFade
setScrollBarDefaultDelayBeforeFade(int)
設定滾動條在淡出隱藏之前延遲多少毫秒
androidiscrollbarFadeDuration
setScrollBarFadeDuration(int)
設定滾動條淡出隱藏過程需要多少秒
android:scrol1barSize
setScrollBarSize(int)
設定垂直滾動條的寬度和水平滾動條的高度
android:scrollbarStyle
setScrollBarStyle(int)
設定滾動條的風格和位置。該屬性支援如下屬性值:
insideOverlay
insidelnset
outsideOverlay
outsidelnset
androidiscrollbarThumbHorizontal
設罝該元件的水平滾動條的滑塊對應的Drawable物件
android:scrollbarThumbVertical
設罝該元件的垂直滾動條的滑塊對應的Drawable物件
android:scrollbarTrackHorizontal
設定該元件的水平滾動條的軌道對應的Drawable物件
android:scrollbarTrackVertical
設定該元件的垂直滾動條的軌道對應的Drawable物件
android:scrollbars
定義該元件滾動時顯示幾個滾動條。 該屬性支援如下厲性值:
none:不顯示滾動條
horizontal:顯示水平滾動條
vertical:顯示垂直滾動條
Android:soundEffectsEnabled
setSoundEffectsEnabled(boolean)
設定該元件被單擊時是否使用音效
android:tag
為該元件設定一個字串型別的tag值。接下來可通過View的getTag()獲取該字串,或通過findViewWithTag() 査找該元件
android:transformPivotX
setPivolX(float)
設定該元件旋轉時中心的X座標
android:transformPivotY
setPivolY(float)
設定該元件旋轉時中心的Y座標
android:translationX
setTranslationX(float)
設定該元件在X方向上的位移
android:translationY
setTranslationY(float)
設定該元件在Y方向上的位移
android:translationZ
setTranslationZ(float)
設定該元件在Z方向上的位移
android:visibility
setVisibility(int)
設定該元件時候可見
ViewGroup繼承了 View類,當然也可以當成普通View來使用,但ViewGroup主要還是當成容器類使用。但由於ViewGroup是一個抽象類,因此實際使用中通常總是使用ViewGroup 的子類來作為容器,例如各種佈局管理器。
ViewGroup容器控制其子元件的分佈依賴於ViewGroup.LayoutParams、ViewGroup. MarginLayoutParams兩個內部類。這兩個內部類中都提供了一些XML屬性,ViewGroup容器中的子元件可以指定這些XML屬性。
其中ViewGroup.LayoutParams所支援的兩個XML屬性如下:
android:layout_width:指定該元件的佈局寬度。
android:layout_height:指定該元件的佈局高度。
關於上面這兩個屬性,其屬性值一般為如下3個屬性值其一。
fill_parent:
指定子元件的高度、寬度與父容器元件的高度、寬度相同(實際上還要減去填充的空白距離)。
match_parent:
該屬性值與fill_parent完全相同,而且從Android 2.2開始就推薦使用這個屬性值來代替fill_parent。
wrap_content:
指定子元件的大小恰好能包裹它的內容即可。
除了以上這3個屬性值,還可以指定具體的寬高畫素值,如80dp。其中dp為一個尺寸單位。
在正式學習Android元件之前,先來一起了解幾個基本概念。
px:
畫素(pixels),1px代表螢幕上一個物理的畫素點。px單位不被建議使用,因為同樣100px的圖片,在不同手機上顯示的實際大小可能不同。偶爾用到px的情況,是需要畫1畫素表格線或陰影線的時候,用其他單位如dp會顯得模糊。
dp:
裝置獨立畫素(Density-independent pixel),一種基於螢幕密度的抽象單位。在每英寸160點的顯示器上,1dp=1px,但隨著螢幕密度的改變,dp與px的換算會發生改變,換算公式為dips=(pixs*160)/densityDpi。
dip:
裝置獨立畫素,與dp完全相同,只是名字不同而已。在早期的Android版本里多使用dip,後來為了與sp統一就建議使用dp。
sp:
比例畫素(scale-independent pixel),主要處理字型的大小,可以根據使用者的字型大小首選項進行縮放。當文字尺寸是“正常”時1sp=1dp=0.00625英寸,而當文字尺寸是“大”或“超大”時1sp>1dp=0.00625英寸。
in:
英寸,標準長度單位,1英寸=2.54釐米(約)。
mm:
毫米,標準長度單位。
pt:
磅(point),標準長度單位,1pt=1/72英寸=0.035釐米。
ppi:
每英寸畫素數(pixel per inch),該值越高,則螢幕越細膩。
dpi:
每英寸多少點(dot per inch),該值越高,則圖片越細膩。
安卓端螢幕大小各不相同,根據其畫素密度,主要分為幾種規格,如下表所示。
密度
ldpi
mdpi
hdpi
xhdpi
xxhdpi
密度值
120
160
240
320
480
密度值比
0.75
1
1.5
2
3
代表解析度
240*320
320*480
480*800
720*1280
1080*1920
ViewGroup.MarginLayoutParams用於控制子元件周圍的頁邊距(Margin,也就是元件四周的空白),它支援的XML屬性如下表所示。
XML屬性
相關方法
說明
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)
指定該子元件上邊的頁邊距
三、建立UI介面
在前面的內容指出過,Android推薦使用XML佈局檔案來定義使用者介面,而不是使用Java程式碼來開發使用者介面,所有元件都提供了兩種方式來控制組件的行為。
在XML佈局檔案中通過XML屬性進行控制。
在Java程式程式碼中通過呼叫方法進行控制。
實際上不管使用哪種方式,它們控制Android使用者介面行為的本質是完全一樣的。大部分時候,控制UI元件的XML屬性還有對應的方法。UI介面的建立主要分為如下三種情況。
3.1使用XML佈局檔案 實際上在建立HelloWorld應用程式的時候就是使用該方法,這種方法是Android推薦使用的,不僅簡單、明瞭,而且可以將應用的檢視控制邏輯從Java程式碼中分離出來,放入XML檔案中控制,從而更好地體現MVC原則。
當我們在Android應用的app/src/main/res/layout目錄下定義一個XML佈局檔案之後(R.java會自動收錄該佈局資源),Java程式碼可通過如下方法在Activity中顯示該檢視:
setContentView ( R . layout .<資原始檔名字>);
當在佈局檔案中新增多個UI元件時,都可以為該UI元件指定android:id屬性,該屬性的屬性值代表該元件的唯一標識。接下來如果希望在Java程式碼中訪問指定UI元件,則可通過如下程式碼來訪問它:
findViewByld ( R . id .< android . id 屬性值>);
一旦在Java程式中獲得指定UI元件之後,接下來就可以通過程式碼來控制各UI元件的外觀行為了,包括為UI元件繫結事件監聽器等。
3.2使用Java程式碼 雖然Android推薦使用XML佈局檔案來控制UI介面,但如果開發者願意,Android允許開發者完全在Java程式碼中控制UI介面。 如果希望在程式碼中控制UI介面,那麼所有的UI元件都將通過new關鍵字創建出來,然後以合適的方式新增到UI介面即可。
為了更好的學習這一塊內容內容,在HelloWorld工程中將app/src/main/java/MainActivity.java檔案的程式碼修改一下,具體控制程式碼如下:
public
class
MainActivity extends AppCompatActivity
{
@Override
protected
void onCreate ( Bundle savedInstanceState )
{
super
. onCreate ( savedInstanceState );
//setContentView(R.layout.activity_main);
// 建立一個線性佈局
LinearLayout layout
new
LinearLayout ( this );
layout
. setOrientation ( LinearLayout . VERTICAL );
// 建立一個顯示Hello World!的TextView
TextView show
new
TextView ( this );
show
. setText ( “Hello World!” );
// 向layout容器新增一個TextView
layout
. addView ( show );
// 設定該Activity顯示layout
setContentView
( layout );
}
}
從上面程式的字程式碼可以看出,該程式中所用到的UI元件都是通過new關鍵字創建出來的,然後程式使用LinearLayout容器來容納這些UI元件,這樣就組成了圖形使用者介面。
從上面的程式程式碼中可以看出,建立UI元件時需要傳入一個this引數,這是由於Context代表訪問Android應用環境的全域性資訊的 API。讓UI元件持有一個Context引數,可以讓這些UI元件通過該Context引數來獲取Android 應用環境的全域性資訊。Context本身是一個抽象類,Android應用的 Activity、Service 都繼承了 Context,因此Activity、Service都可直接作為Context使用。關於這一塊的內容現在可能會看不太懂,不過沒關係,經過後續的學習就明白了。
通過XML佈局和通過Java程式碼都可以實現同樣的功能,但是發現通過Java程式碼實現程式非常臃腫,而用XML佈局程式碼要簡單得多,因此在開發中不推薦使用這種方式。
3.3混合使用XML佈局檔案和Java程式碼 前面己經提到,完全使用Java程式碼來控制UI介面不僅煩瑣,而且不利於解耦;而完全利用XML佈局檔案來控制UI介面雖然方便、便捷,但難免有失靈活。因此有些時候,可能需要混合使用XML佈局檔案和程式碼來控制UI介面。
當混合使用XML佈局檔案和程式碼來控制UI介面時,習慣上把變化小、行為比較固定的元件放在XML佈局檔案中管理,而那些變化較多、行為控制比較複雜的元件則交給Java程式碼來管理。