安卓:View的基本信息

public class

View

extends Object

implements 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)設置可見性


注意:安卓框架對測量,佈局和繪製圖形負責。你不應該調用這些方法來執行相應的行爲,除非你確實實現了ViewGroup。

Implementing a Custom View   實現自定義的View

實現自己的View,覆蓋下面框架的幾個回調方法即可。你不需要重寫所有的方法。事實上,你可用從重寫onDraw(android.graphics.Canvas)開始

Category Methods Description
Creation

Constructors

構造體

有一種從代碼創建或者從佈局文件膨脹時調用,另一種是粘貼及應用佈局文件中定義的屬性。

onFinishInflate()

當其子類完成膨脹時調用.

Layout onMeasure(int, int)

當決定view和它的孩子的尺寸時調用.

onLayout(boolean, int, int, int, int) Called when this view should assign a size and position to all of its children.
onSizeChanged(int, int, int, int) Called when the size of this view has changed.
Drawing onDraw(android.graphics.Canvas) Called when the view should render its content.

Event processing

事件

處理

onKeyDown(int, KeyEvent) Called when a new hardware key event occurs.
onKeyUp(int, KeyEvent) Called when a hardware key up event occurs.
onTrackballEvent(MotionEvent) Called when a trackball motion event occurs.
onTouchEvent(MotionEvent) Called when a touch screen motion event occurs.

Focus

焦點

onFocusChanged(boolean, int, android.graphics.Rect) Called when the view gains or loses focus.
onWindowFocusChanged(boolean) Called when the window containing the view gains or loses focus.

Attaching

依附

onAttachedToWindow() Called when the view is attached to a window.
onDetachedFromWindow() Called when the view is detached from its window.
onWindowVisibilityChanged(int) 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


發佈了34 篇原創文章 · 獲贊 0 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章