作為一個Android開發者,工作中肯定或多或少都會跟自定義View打交道,但是我們的第一反應就是這太難了,去網上找找,看看有沒有現成的可以拿來直接用的。
其實之所以我們覺得自定義View很難,根本原因還是我們對於View的基礎掌握不牢。
今天這篇文章,我就帶大家一起重新學習一下View的基礎。
View的建構函式
1.View(Context)
在Java程式碼裡面直接new的時候呼叫。
2. View(Context, AttributeSet)
在.xml
裡宣告的時候呼叫,AttributeSet
是從.xml
中解析出來的屬性集合。
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/icon" />
複製程式碼
上面.xml
中的layout_width
, layout_height
以及src
是從哪裡來的?它們可不是憑空產生的;實際上是通過<declare-styleable>
把這些屬性明確的宣告為系統需要處理的東西。比如,src就是在這裡定義的:
<declare-styleable name="ImageView">
<!-- Sets a drawable as the content of this ImageView. -->
<attr name="src" format="reference|color" />
</declare-styleable>
複製程式碼
每個declare-styleable
產生一個R.styleable.[name]
,外加每個屬性的R.styleable.[name]_[attribute]
。比如,上面的程式碼產生 R.styleable.ImageView
和R.styleable.ImageView_src
。
這些資源是什麼東西呢?R.styleable.[name]
是所有屬性資源的陣列,系統使用它來查詢屬性值。每個R.styleable.[name]_[attribute]
只不過是這個陣列的索引罷了,所以你可以一次性取出所有屬性,然後按索引分別查詢每個的值。
xml
中屬性是以AttributeSet
的形式通過構造方法傳遞給View
的,但通常我們不直接使用AttributeSet
。而是使用Theme.obtainStyledAttributes()
。這是因為原始的屬性通常需要引用和應用樣式。比如,如果你在XML中定義了style=@style/MyStyle
,這個方法先獲取MyStyle
,然後把它的屬性混合進去。最終obtainStyledAttributes()
返回一個TypedArray
,你可以用它來獲取屬性值。這個過程簡化之後就像這樣:
public ImageView(Context context, AttributeSet attrs) {
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ImageView, 0, 0);
Drawable src = ta.getDrawable(R.styleable.ImageView_src);
setImageDrawable(src);
ta.recycle();
}
複製程式碼
這裡我們向obtainStyledAttributes()
傳遞了兩個引數。第一個引數是AttributeSet attrs
,即xml中的屬性;第二個引數是R.styleable.ImageView
陣列,它告訴這個方法我們想取哪個屬性的值,這裡表示要獲取ImageView
屬性的值;第三和第四個引數是兩個資源引用defStyleAttr
和defStyleRes
,將在第三和第四個構造方法中進行說明。
當獲得了TypedArray
之後,我們就可以獲取單個屬性了。我們需要使用R.styleable.ImageView_src
來正確索引陣列中的src
屬性。
3. View(Context, AttributeSet, defStyleAttr)
defStyleAttr
引數:預設的Style
,指它在當前Application
或Activity
所用的Theme
中的預設Style
,為某個型別的View
定義這個類的基礎樣式,如果我們不在構造方法傳入指定我們自定義的樣式則將使用Android
系統預設的控制元件樣式,指定時需要間接的通過theme
,如下所示:
1、在Theme(styles.xml)中設定樣式
<resources>
<style name="Theme">
<item name="mStyle">@style/CustomStyle</item>
</style>
<!--具體樣式-->
<style name="CustomStyle" >
<item name="android:background">@android:color/black</item>
</style>
</resource>
複製程式碼
2、在構造方法中使用
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.view, R.attr.mStyle, 0);
複製程式碼
4. View(Context, AttributeSet, defStyleAttr, defStyleRes)
defStyleRes
引數:它只是一個用於指定樣式的style
資源(@style/Widget.TextView
)。比defStyleAttr
簡單,不需要間接的通過theme
。在API 21新增的。因此除非你的minSdkVersion
為21
,否則不要使用它。
它們是串聯的,如果你呼叫了一個,所有的都會通過super
被呼叫。串聯還意味著你只需重寫你需要的建構函式。一般來說,你只需實現前兩個(一個用於程式碼,一個用於XML inflation
)。
View檢視結構
對於多View
的檢視,結構是樹形結構:最頂層是ViewGroup
,ViewGroup
下可能有多個ViewGroup
或View
,如下圖:
注意:無論是
measure
過程、layout
過程還是draw
過程,永遠都是從View
樹的根節點開始測量或計算(即從樹的頂端開始),一層一層、一個分支一個分支地進行(即樹形遞迴),最終計算整個View
樹中各個View
,最終確定整個View
樹的相關屬性。
Android座標系
Android的座標系定義為:
- 螢幕的左上角為座標原點
- 向右為
x
軸增大方向 - 向下為
y
軸增大方向
具體如下圖:
View位置(座標)描述 )
- View的位置由4個頂點決定的(如下圖A、B、C、D)
- 4個頂點的位置描述分別由4個值決定(View的位置是相對於父控制元件而言的):
Top
:子View上邊界到父view上邊界的距離
Left
:子View左邊界到父view左邊界的距離
Bottom
:子View下邊距到父View上邊界的距離
Right
:子View右邊界到父view左邊界的距離
View位置獲取方式
View的位置是通過view.getxxx()
函式進行獲取(以Top為例):
// 獲取Top位置
public final int getTop() {
return mTop;
}
// 其餘如下:
getLeft();//獲取子View左上角距父View左側的距離
getBottom(); //獲取子View右下角距父View頂部的距離
getRight(); //獲取子View右下角距父View左側的距離
複製程式碼
與MotionEvent
中get...()
和getRaw...()
的區別
//get() :觸控點相對於其所在元件座標系的座標
event.getX();
event.getY();
//getRaw() :觸控點相對於螢幕座標系的座標
event.getRawX();
event.getRawY();
複製程式碼
具體如下圖:
Android的角度(angle)與弧度(radian)
角度和弧度都是描述角的一種度量單位,區別如下圖:
在預設的螢幕座標系中角度增大方向為順時針,與數學座標系中角度增大方向剛好相反。
Android中顏色相關內容
Android支援的顏色模式:
以ARGB8888為例介紹顏色定義:
定義顏色的方式
- 在java中定義顏色
//java中使用Color類定義顏色
int color = Color.GRAY; //灰色
//Color類中使用ARGB值表示顏色
int color = Color.argb(127, 255, 0, 0); //半透明紅色
//使用十六進位制定義顏色
int color = 0xaaff0000; //帶有透明度的紅色
//Android中Color工具類 parseColor解析顏色字串
int color = Color.parseColor("#FFFFFF")//白色
複製程式碼
- 在xml檔案中定義顏色
/res/values/color.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
//定義了紅色(沒有alpha(透明)通道)
<color name="red">#ff0000</color>
//定義了藍色(沒有alpha(透明)通道)
<color name="green">#00ff00</color>
</resources>
複製程式碼
- 在
xml
檔案(不侷限與佈局xml
檔案,其它xml
檔案也可以用這種定義方式)中以"#"
開頭定義顏色,後面跟十六進位制的值,有如下幾種定義方式:
#f00 //低精度 - 不帶透明通道紅色 == #ff0000
#af00 //低精度 - 帶透明通道紅色 == #aaff0000
#ff0000 //高精度 - 不帶透明通道紅色
#aaff0000 //高精度 - 帶透明通道紅色
複製程式碼
引用顏色的方式
- 在java檔案中引用
color.xml
中定義的顏色:
int color = getResources().getColor(R.color.mycolor);
複製程式碼
- 在
xml
檔案(layout
或style
)中引用或者建立顏色:
<!--在style檔案中引用-->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">@color/red</item>
</style>
<!--在layout檔案中引用在/res/values/color.xml中定義的顏色-->
android:background="@color/red"
<!--在layout檔案中建立並使用顏色-->
android:background="#ff0000"
複製程式碼
希望這邊文章能對您有所幫助~~~~~~~~