View
extends Objectimplements Drawable.Callback KeyEvent.Callback AccessibilityEventSource
Class Overview
這個類代表了構建用戶交互組件的基本單元。一個View是一塊繪製和接收用戶事件的位於屏幕上的長方形區域。它是widgets的基礎(widgets指用戶交互組件)。而子類ViewGroup則是佈局的基礎(佈局:用於容納其他Views,並定義他們的佈局屬性)。
Developer Guides 開發嚮導
想要知道更多,參閱User Interface開發嚮導。
Using Views 使用
所有處於窗口中的view都被安排在一顆樹上(即只有一個根節點)。你可以從代碼或者特定的XML佈局文件中來添加views。這兒有很多特殊view的子類,他們具有控制或者顯示文本,圖片及其他內容的能力。
一旦你創建views的樹,你可能希望實現幾個典型的通用操作:
設置屬性:可在構建時用XML定義。
設置焦點:調用requestFocus()
設置監聽器:可通知獲得或者失去焦點。子類具有更多監聽事件
設置可見性:使用setVisibility(int)設置可見性
Implementing a Custom View 實現自定義的View
實現自己的View,覆蓋下面框架的幾個回調方法即可。你不需要重寫所有的方法。事實上,你可用從重寫onDraw(android.graphics.Canvas)開始
Category | Methods | Description |
---|---|---|
Creation |
Constructors 構造體 |
有一種從代碼創建或者從佈局文件膨脹時調用,另一種是粘貼及應用佈局文件中定義的屬性。 |
|
當其子類完成膨脹時調用. |
|
Layout |
|
當決定view和它的孩子的尺寸時調用. |
|
Called when this view should assign a size and position to all of its children. | |
|
Called when the size of this view has changed. | |
Drawing |
|
Called when the view should render its content. |
Event processing 事件 處理 |
|
Called when a new hardware key event occurs. |
|
Called when a hardware key up event occurs. | |
|
Called when a trackball motion event occurs. | |
|
Called when a touch screen motion event occurs. | |
Focus 焦點 |
|
Called when the view gains or loses focus. |
|
Called when the window containing the view gains or loses focus. | |
Attaching 依附 |
|
Called when the view is attached to a window. |
|
Called when the view is detached from its window. | |
|
Called when the visibility of the window containing the view has changed. |
IDs
Views有很多整形id與其相關。這些id被分配到XML佈局文件中,用於尋找特定的view。通用模式如下:
- 定義一個佈局文件並賦予其唯一ID
<Button android:id="@+id/my_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/my_button_text"/>
- 在Activity中的onCreate回調方法中找到這個button.
Button myButton = (Button) findViewById(R.id.my_button);
視圖的ID並不需要在整個樹中唯一,但是最佳實踐是讓它在你搜索的那一部分樹上唯一。
Position 位置
View是長方體,它爲座標指的是距離左/上 距離,計量單位是像素。
一種可能的檢索view位置的方式是調用 和 方法。前者返回 左(X),後者返回 上(Y)。返回值都是相對於父容器的。舉個例子,當getLeft()返回20,它意味着它距離它的直接父容器左邊的距離爲20。
額外的,一些便利類可以讓你減少計算,例如getRight()
和 getBottom().
Size, padding and margins 尺寸,填充 和 邊緣
The size of a view is expressed with a width and a height. A view actually possess two pairs of width and height values.
尺寸代表了寬度和高度,這兒有兩種標準:
第一種被稱做:測量寬度和測量高度。這些尺寸定義了views想要在它的父容器中有多大。通過調用getMeasuredWidth()
and getMeasuredHeight()
取得這些尺寸。
第二種就是 寬度和高度,也叫做 繪製寬度 和繪製高度。這些尺寸定義了,在佈局完成後繪製時,實際繪製在屏幕上的實際尺寸。通過調用 getWidth()
and getHeight()
獲得這些尺寸。
For instance, a left padding of 2 will push the view's content by 2 pixels to the right of the left edge. Padding can be set using the setPadding(int,
int, int, int)
or setPaddingRelative(int,
int, int, int)
method and queried by calling getPaddingLeft()
, getPaddingTop()
, getPaddingRight()
, getPaddingBottom()
, getPaddingStart()
, getPaddingEnd()
.
在繪製尺寸時,view是將填充也計算在內了的。填充以像素表示,具有左、上、右、下四個部分。填充使得view的內容能夠以指定的像素進行偏移。舉個例子,左邊2的填充意味着view的內容向右邊移動了2個像素。你可以使用下面這些方法:
setPadding(int,
int, int, int)
, setPaddingRelative(int,
int, int,int)
,
getPaddingLeft()
, getPaddingTop()
,
getPaddingRight()
, getPaddingBottom()
, getPaddingStart()
, getPaddingEnd()
.
儘管view定義了填充,但是沒有對 邊緣(margins) 提供任何支持,它被放在了 ViewGroup
和ViewGroup.MarginLayoutParams
中了。
Layout 佈局
佈局有兩個過程:測量和佈局。測量實現了measure(int, int),它自頂向下的遍歷了view樹。在遞歸過程中,每個view被分配了特定的尺寸。在測量完成後,每個view將存儲他的測量值。第二步在 中,它也是自頂向下的.在這一步中,每個父容器都使用在上一步得到的值來計算子view的位置。
在view完成了measure方法返回後,getMeasuredWidth()
和getMeasuredHeight()值必須被設置。一個view的測量寬度和測量高度值必須遵循父view的限制。這可以保證,在測量後,所有的父親都能夠接受子View的測量。父View可能不止一次調用子的measure()。舉個例子,父view可能測量子View使用的是不確定的尺寸,來找出它想要多大,然後再一次使用實際值調用measure(),如果所有子類未加限制的尺寸過大或者太小
測量經過兩個類計算尺寸。View.MeasureSpec類用於告知父類他們想怎樣被測量和定位。基本的LayoutParams類只是描述他們想要的高度和寬度。對於每一個維度:可以指定爲以下幾個值:
- 確切的數字
- MATCH_PARENT,這意味着它們想和父容器一樣大(減去padding)
- WRAP_CONTENT,這意味着他們只想和他們包含的內容一樣大(加上padding)
有不同的LayoutParams子類對應着不同的ViewGroup的子類。舉個例子,絕對佈局擁有可以添加X和Y的佈局子類。
測量空間(MeasureSpecs)用於自上而下的推送需求。測量空間可以是下面三種的一種:
- 未指定的(UNSPECIFIED):這用於父容器絕對子類視圖尺寸。舉個例子,線性佈局可能通過調用 子類的measure()方法,通過設定高度爲UNSPECIFIED以及240確切的寬度來發覺子類在給予240像素寬度時,子視圖需要的高度。
- 確切的(EXACTLY):這用於父容器強加一個確切的數給其子類。子類必須使用這個尺寸,這保證了所有其子孫視圖都會適配這個值。
- 最大的(AT_MOST):這用於父容器強加一個最大值給其子類。子類必須保證自己和子孫視圖適配這個值。
爲了初始化佈局,調用requestLayout() 。這個方法典型的應用是視圖認爲自身不在適配當前的邊界。
Drawing 繪製
繪製是通過遍歷和將視圖插入到無效區域(未被使用區域)來完成的。由於樹的遍歷是有順序的,這意味着父節點會先繪製前面的,然後纔是它的兄弟。如果你給一個VIEW設定了背景drawable,那view將會在爲你先繪製,然後才調用它的onDraw()
方法。
注意:在非無效區域的視圖是不會被框架所繪製的。
爲了強制完成繪製工作,調用invalidate()
.
Event Handling and Threading 事件處理和線程
一個view基本的週期如下:
1. 一個事件到來並被分配給合適的view。這個view將事件通知給任何註冊的監聽者。
2. 在處理事件中,視圖的邊界可能需要改變,調用requestLayout() 。
3. 相似的,如果在處理事件過程中需要更新界面,調用invalidate() 。
4. 如果requestLayout()或者invalidate()被調用了,框架將會處理 測量,佈局和繪製工作。
注意:整個視圖樹是單一的線程。當你調用任何視圖的方法時,你總是處於UI線程中。如果你在工作線程中想要更新視圖的狀態,你應該使用Handler。
Focus Handling 焦點處理
框架將會例行的響應用戶輸入的響應。這包含了當視圖移除或者隱藏起來,新的視圖出現時等改變。視圖在方法isFocusable()中表明瞭他們想要獲得焦點的意願。去改變一個視圖的焦點,調用setFocusable(boolean),而不管它是否能夠獲得焦點。當在觸屏模式下,視圖表明他們是否願意通過isFocusableInTouchMode()
獲得焦點,或者通過 setFocusableInTouchMode(boolean)
改變焦點。
焦點移動是基於給定方向的最近鄰居算法。在很少的情況下,算法和開發者想要的效果不一致。在這些情況下,你才需要顯示的在XML佈局文件中覆蓋這些屬性。
nextFocusDown
nextFocusLeft
nextFocusRight
nextFocusUp
爲了讓特殊的VIEW獲得焦點,調用requestFocus()。
Touch Mode 觸摸模式
當用戶經由類似D-pad的直接案件導航到用戶接口,這有必要聚焦到用戶所見的輸入控件上。如果設備有觸摸能力,那麼,所有的用戶都以觸摸方式完成交互,那麼高亮或者給予特定視圖焦點就不再有必要。這種模式也就是“觸摸模式”。
對於具有觸摸能力的設備,一旦用戶觸摸屏幕,設備即進入觸摸模式。從這一點往後,只有isFocusableInTouchMode()爲真的視圖纔會繼續擁有焦點,例如編輯小部件。其他的視圖是可觸摸的,例如按鈕,在被觸摸時,將不會獲得焦點。他們僅僅是響應用戶的點擊行爲。
Any time a user hits a directional key, such as a D-pad direction, the view device will exit touch mode, and find a view to take focus, so that the user may resume interacting with the user interface without touching the screen again.
任何用戶直接的按鍵,例如直接 D-pad,視圖設備將會推出點擊模式,然後發現一個View來獲得焦點,然後用戶可以恢復交互直到用戶再次點擊。
觸摸模式可在活動間傳播。調用isInTouchMode()來觀察設備當前是否處於觸摸模式。
Scrolling 滾動
框架對於需要滾動內部內容的視圖提供基本的支持。這包含了跟蹤X和Y的滾動偏移,以便繪製滾動條的位置。更多細節見 scrollBy(int,
int)
, scrollTo(int,
int)
, 和 awakenScrollBars()
Tags 標記
不同於ID,標記並不用於標識視圖。標記用於爲VIEW添加額外的信息片段。他們最常用於作爲view自身便利的數據存儲,而無需放在額外的數據結構中。
Properties 屬性
View類曝光了ALPHA屬性,作爲幾種平臺相關的屬性,例如TRANSLATION_X
和 TRANSLATION_Y。和他們的屬性既可以以屬性方式,也可以用 setter/getter方法。
Animation 動畫
自安卓3.0開始,更好使用動畫的方式是使用android.animation
包中的API。這些基於動畫的類改變了視圖實際的屬性,例如透明度和偏移X(alpha
and translationX
)。
Security 安全
有時候確認一個行爲是用戶完全的行爲是有畢業的,例如權限的確認,執行一次購買,或者點擊廣告。不幸的是,惡意程序可能嘗試欺騙用戶無意識的執行這些行爲。作爲一種補救措施,框架提供一種可用語提交視圖訪問敏感功能的點擊過濾機制。
爲了使用點擊過濾,調用setFilterTouchesWhenObscured(boolean)
或者設置
。當能夠使用時,框架將會放棄 。作爲結果,當有Toast,對話框或者窗口出現在視圖窗口的上方時,視圖將不會接受點擊事件。
對於更多細力度的安全控制,考慮覆蓋onFilterTouchEventForSecurity(MotionEvent) 方法來實現你自己的安全策略。參考:FLAG_WINDOW_IS_OBSCURED