1. 程式人生 > >Android安全/開發基礎--10--圖形介面(UI)和碎片(Fragment)(上)

Android安全/開發基礎--10--圖形介面(UI)和碎片(Fragment)(上)

10-1、View理論

View的事件體系

View是Android中所有控制元件的基類。ViewGroup是控制元件組,內部包含了許多控制元件。 view的四個位置屬性:top、left、right、bottom

在這裡插入圖片描述

MotionEvent:手指接觸屏幕後產生的一些典型事件型別。

ACTION_DOWN:手指剛接觸螢幕
ACTION_MOVE:手指在螢幕上移動
ACTION_UP:手指從螢幕上鬆開的一瞬間

TouchSlop:系統所能識別出的被認為是滑動的最小距離。

通過三種方式可以實現View的滑動:

1、通過View本身提供的scrollTo和scrollBy方法來實現滑動。操作簡單,適合對View內容的滑動。 2、通過動畫給View施加平移效果來實現滑動。操作簡單,適合沒有互動的View和實現複雜的動畫效果。 3、通過改變View的佈局引數LayoutParams使得View重新佈局從而實現滑動。操作簡單,適合有互動的View。

實現彈性滑動(漸近式滑動)的三種方法:

1、使用Scroller:不斷讓View進行重繪,每一次重繪都會導致View進行小幅度的滑動,而多次的小幅度滑動就組成了彈性滑動。 2、通過動畫:通過改變一個百分比配合scrollTo方法來完成View的滑動。採用這種方法還可以實現其它動畫效果。 3、使用延時策略:通過傳送一系列延時訊息從而達到一種漸近式的效果。具體來說可以使用Handler或View的postDelayed方法,也可以使用執行緒的sleep方法。

點選事件的傳遞規則:

一個點選事件產生後,它傳遞過程的順序為:Activity–>Window–>View,即事件總是先傳遞給Activity,Activity再傳遞給Window,最後Window再傳遞給頂級View。頂級View接收到事件後,就會按照事件分發機制去分發事件。

響應使用者的點選常用解決方案是設定OnClickListener監聽器。

頂級View對點選事件的分發過程:

點選事件達到頂級View(一般是一個ViewGroup)以後,會呼叫ViewGroup的dispatchTouchEvent方法。然後的邏輯為:如果頂級ViewGroup攔截事件即onInterceptTouchEvent返回true,則事件由ViewGroup處理,這時如果ViewGroup的mOnTouchListener被設定,則onTouch會被呼叫,否則onTouchEvent會被呼叫。

View的三大流程:measure、layout、draw

measure:測量。確定View的測量寬/高。具體過程:如果只是一個原始的View,那麼通過measure方法就完成了其測量過程。如果是一個ViewGroup,除了完成自己的測量過程外,還會遍歷去呼叫所有元素的measure方法,各個子元素再遞迴去執行這個流程。完成以後通過getMeasuredWidth和getMeasuredHeight方法來獲取到View測量後的寬/高。

layout:佈局。確定View的最終寬/高和四個頂點的位置。具體過程:首先會通過setFrame方法來設定View的四個頂點的位置,即初始化mLeft、mRight、mTop、mBottom這四個值,View的四個頂點確定則View在父容器(ViewGroup)中的位置確定。接著會呼叫onLayout方法,在onLayout中會遍歷所有的子元素並呼叫其layout方法,在layout方法中onLayout方法又會被呼叫。即layout方法確定View本身的位置,而onLayout方法則會確定所有子元素的位置。完成以後通過getTop、getBottom、getLeft、getRight來拿到View的四個頂點的位置,通過getWidth和getHeight方法來拿到View的最終寬/高。

draw:繪製。將View繪製的螢幕上。具體過程:繪製背景background.draw (canvas),繪製自己 (onDraw),繪製children (dispatchDraw),繪製裝飾 (onDrawScrollBars)。完成以後View的內容顯示到螢幕上。

自定義View的分類:

繼承View重寫onDraw方法:用於實現一些不規則的效果,一般需要重寫onDraw方法。

繼承ViewGroup派生特殊的Layout:用於實現自定義佈局,需要合適的處理ViewGroup的測量、佈局這兩個過程,並同時處理子元素的測量和佈局過程。

繼承特定的View(比如:TextView):用於擴充套件某種已有的View的功能。比如TextView。

繼承特定的ViewGroup(比如:LinearLayout):實現看起來很像幾種View組合在一起的效果。

注意事項:讓View支援wrap_content。若有必要則讓View支援padding。儘量不要在View中使用Handler。View中如果有執行緒或動畫需要及時停止。View帶有滑動巢狀情形時需要處理好滑動衝突。

10-2、佈局 (layout)

佈局(layout)定義了一系列使用者介面物件以及它們顯示在螢幕上的位置。組成佈局的定義儲存在XML檔案中。每個定義用來建立螢幕上的一個物件,如按鈕或文字資訊。

元件是使用者介面的構造模組(即XML佈局檔案)。元件可以顯示文字或影象,與使用者互動,甚至佈置螢幕上的其他元件。按鈕、文字輸入控制元件和選擇框等都是元件。控制組件大小有三個選擇:讓元件自己決定;手動調整;讓元件充滿約束佈局。

建立佈局檔案:在專案工具視窗中,右鍵單擊res/layout資料夾, 選擇New → Layout resourcefile選單項。命名佈局檔案。輸入例如LinearLayout作為根元素節點完成建立。

在佈局XML檔案中,凡是以layout_開頭的屬性都屬於佈局引數。與其他屬性不同的是,元件的佈局引數是用來向其父元件做指示的,即用於告訴父佈局如何安排自己。

在一個佈局上新增一個子佈局,除了使用巢狀佈局外還可以使用ConstraintLayout工具給佈局新增一系列約束。想要在ConstraintLayout(父佈局)里布置檢視就不用再麻煩地拖來拖去了。注意,開發工具無法校驗佈局XML內容,拼寫錯誤早晚會出問題,應儘量避免。

約束編輯器:首先選中一個元件檢視,在靠近佈局預覽視窗頂部的工具欄上,你可以看到一些約束編輯選項。主要有顯示所有約束、自動連線切換開關、清除全部約束、猜測約束。

檢視右邊的屬性檢視視窗,水平方向和豎直方向的尺寸是分別由寬度設定和高度設定決定的。能設定的值有以下三種。每種值都對應layout_width或layout_height的一個值。

檢視尺寸設定型別:

設定型別 設定值 用法
固定大小 Xdp 以dp為單位,為檢視指定固定值
包裹內容 wrap_content 設定檢視想要的尺寸(隨內容走),也就是說,大到足夠容納內容
動態適應 0dp 允許檢視縮放以滿足指定約束

佈局XML檔案中的單位:

設定型別 設定值
px 畫素。不推薦使用px,因為它不會根據螢幕密度自動縮放。
dp/dip 密度無關畫素。1dp在裝置螢幕上總是等於1/160英寸。無論螢幕密度如何,總能獲得同樣的尺寸。
sp 縮放無關畫素。通常使用sp來設定螢幕上的字型大小。
pt、 mm、 in 類似於dp的縮放單位,允許以點(1/72英寸)、毫米或英寸為單位指定使用者介面尺寸。但在實際開發中不建議使用這些單位,因為並非所有裝置都能按照這些單位進行正確的尺寸縮放配置。

實際開發中,通常只會用到dp和sp這兩種單位。

邊距和內邊距:

邊距屬性是佈局引數,決定了元件間的距離。邊距必須由該元件的父元件負責。 內邊距不是佈局引數。屬性android:padding告訴元件:在繪製元件自身時,要比所含內容大多少。

10-3、Android介面的四種基本佈局

線性佈局:LinearLayout

將其所包含的控制元件線上性方向上依次排列。通過android:orientation屬性指定。

相對佈局:RelativeLayout

通過相對定位的方式讓控制元件出現在佈局的任何位置。共有3組相對定位:相對父佈局(螢幕)定位、相對控制元件定位、另一種相對控制元件的定位。

幀佈局:FrameLayout

所有控制元件都會預設擺在佈局的左上角。應用場景極少。

百分比佈局:

指定控制元件在佈局中所佔的百分比。它只是FrameLayout和RelativeLayout的擴充套件。屬於新增佈局。若使用該佈局需要在build.gradle中新增百分比分佈庫的依賴,即可正常使用。 PercentFrameLayout:繼承FrameLayout的所有屬性,所有控制元件預設在左上角。 PercentRelativeLayout:繼承了RelativeLayout的所有屬性。

10-4、控制元件常用的元件屬性

屬性值不是字串值,而是對字串資源的引用。字串資源包含在一個獨立的名叫strings.xml檔案中。通常將文字內容放置在獨立的字串資源XML檔案中,然後引用它們。

android:layout_width (寬) 和 android:layout_height (高) :
	fill_parent:讓當前控制元件的大小和父佈局的大小一樣,也就是由父佈局來決定當前控制元件的大小。
	match_parent:檢視與其父檢視大小相同。若父檢視和螢幕一樣寬,則該屬性代表和螢幕一樣寬,它和fill_parent意義相同,但官方更推薦使用match_parent。
	wrap_content:檢視將根據其顯示內容自動調整大小。
	android:padding (字號大小):以dp為單位。
	android:text (顯示文字內容)。

android:orientation (決定水平還是垂直):
	horizontal:佈局內的控制元件橫向排列。
	vertical:佈局內控制元件縱向排列。

android:vidibility (決定控制元件可見性):
	visible:控制元件是可見的。該屬性是預設值,如果不指定具體屬性則預設使用該屬性。
	invisible:控制元件不可見。但控制元件仍佔據原來的位置和大小,只是變為透明狀態了。
	gone:控制元件不可見。同時也不佔據任何螢幕空間。

10-5、佈局是一種資源

資源是應用非程式碼形式的內容,如影象檔案、音訊檔案以及XML檔案等。專案的所有資原始檔都存放在目錄app/res的子目錄下。科普:dpi:解析度單位。代表每一英寸長有多少個畫素點數。

drawable-mdpi:  中等畫素密度螢幕(約160dpi),在app/src/main/res目錄中
drawable-hdpi:   高畫素密度螢幕(約240dpi)
drawable-xhdpi: 超高畫素密度螢幕(約320dpi)
drawable-xxhdpi:超超高畫素密度螢幕(約480dpi)

展開目錄app/build/generated/source/r/debug,專案包名稱中的R.java檔案。即平時所用到的如:

mTrueButton = (Button) findViewById(R.id.true_button);     
//以元件的資源ID作為引數,返回一個檢視物件。注意,賦值前必須先將返回的View型別轉換,此處為:(Button)

10-6、Drawable的分類

BitmapDrawable:表示的就是一張圖片。它各個屬性的含義:

android:src:圖片資源的id
android:antialias:是否開啟圖片抗鋸齒功能,開啟會讓圖片變得平滑但也降低了清晰度。
android:dither:是否開啟抖動效果,圖片畫素和螢幕畫素不一致時,開啟可保持較好的顯示。
android:filter:是否開啟過濾效果,圖片尺寸被拉昇或壓縮時,開啟可保持較好的顯示。
android:gravity:圖片小於容器尺寸時,設定此選項可以對圖片進行定位。
android:mipMap:紋理對映,不常用,預設值為false。
android:tileMode:平鋪模式。選項值有disabled(預設)、clamp、repeat、mirror。

ShapeDrawable:通過顏色構造圖形。圖形即可純色也可漸變。它各個屬性含義:

android:shape:表示圖形的形狀。選項值有rectangle(矩形,預設值)、oval(橢圓)、line(橫線)、ring(圓環)。
<corners>:表示shape的四個角的角度。只適用於矩形shape。
<gradient>:表示漸變效果。與<solid>標籤是相互排斥的。
<solid>:表示純色填充。
<stroke>:Shape的描邊。
<padding>:表示空白。包含它的View的空白。屬性值:android:left、android:top、android:right、android:bottom。
<size>:shape的大小。屬性值:android:width、android:height。shape的寬/高。

LayerDrawable:表示一種層次化的Drawable集合,實現疊加效果。它各個屬性的含義:

android:top:Drawable相對於View的上偏移量。單位為畫素,下同。
android:bottom:Drawable相對於View的下偏移量。
android:left:Drawable相對於View的左偏移量。
android:right:Drawable相對於View的右偏移量。

StateListDrawable:表示Drawable集合。主要用於設定可單擊的View背景,最常見的是Button。

android:constantSize:
		True表示StateListDrawable的固有大小保持不變,false則會隨著狀態的改變而改變,預設值為false。
android:dither:
		是否開啟抖動效果,圖片畫素和螢幕畫素不一致時,開啟抖動可保持較好的顯示,預設值為true。
android:variablePadding:
		True表示StateListDrawable的padding隨著狀態的改變而改變,false表示StateListDrawable的padding是內部所有Drawable的padding的最大值。預設值為false。

LevelListDrawable:表示一個Drawable集合,集合中的每個Drawable都有一個等級概念,根據不同的等級,LevelListDrawable會切換為對應的Drawable。

TransitionDrawable:用於實現兩個Drawable之間的淡入淡出效果。它的屬性有:android:top、android:bottom、android:left、android:right。

InsetDrawable:可以將其它Drawable內嵌到自己當中,並可以在四周留出一定的間距。它的屬性有:android:top、android:bottom、android:left、android:right。除此還有:

android:insetTop和android:insetBottom:頂部的大小和底部的大小。
android:insetLeft和android:insetRight:左邊內凹的大小和右邊內凹的大小。

ScaleDrawable:根據自己的等級將指定的Drawable縮放到一定比例。屬性含義:

android:scaleWidth和android:scaleHeight:表示指定Drawable寬和高的縮放比例,以百分比的形式表示。

ClipDrawable:根據自己當前的等級來裁剪另一個Drawable。等級範圍為[0,10000],0是預設值,表示完全裁剪。

10-7、單例

單例是特殊的Java類,在建立例項時,一個單例類僅允許建立一個例項。應用能在記憶體裡活多久,單例就能活多久。要建立單例,需建立一個帶有私有構造方法及get()方法的類。如果例項已存在,get()方法就直接返回它。如果例項還不存在,get()方法就會呼叫構造方法建立它。

優點:單例能方便地儲存和控制模型物件。 缺點:單例無法做到持久儲存,還不利於單元測試。

10-8、碎片(Fragment)

定義:碎片是一種可以嵌入在活動當中的UI片段,可以讓程式更加合理和充分的利用大螢幕的空間。可以理解為將螢幕劃分為好多個板塊。碎片通常在平板開發中使用。

動態新增碎片的步驟:

1、建立待新增的碎片例項。 2、獲取FragmentManager,在活動中可以直接通過呼叫getSupportFragmentManager()方法得到。 3、開啟一個事物,通過呼叫beginTransaction()方法開啟。 4、向容器內新增或替換碎片,一般使用replace()方法實現,需要傳入容器的id和待新增的碎片例項。 5、提交事務,呼叫commit()方法來完成。如此即完成了在活動中動態新增碎片的功能。

碎片的生命週期:

執行狀態:當一個碎片可見,並且它所關聯的活動正處於執行狀態時,該碎片也處於執行狀態。 暫停狀態:當一個活動進入暫停狀態時,與它相關聯的可見碎片也會進入暫停狀態。 停止狀態:當一個活動處於停止狀態時,與它相關聯的碎片也處於停止狀態。 銷燬狀態:當活動被銷燬時,與它相關聯的碎片也會進入銷燬狀態。

Fragment類中也提供了一系列的回撥方法,以覆蓋碎片生命週期的每個環節:

onAttach():當碎片和活動建立關聯的時候呼叫。
onCreateView():為碎片建立檢視(載入佈局)時呼叫。
onActivityCreated():確保與碎片和相關聯的活動一定已經建立完畢的時候呼叫。
onDestroyView():當與碎片關聯的檢視被移除的時候呼叫。
onDetach():當碎片和活動解除關聯的時候呼叫。