自定義View(一)、基礎概念和知識點
接下來一段時間我們將整理一系列自定義View文章,由淺到難,磨刀不誤砍柴工,在真正開始之前,我們還是對自定義View的知識點有一定的瞭解和補充。
一、座標系
爲什麼座標系要提出來講,因爲在Android中和我們傳統的座標系有一定的區別,我們需要做區分。
- 數學座標系:
右爲X軸的正方向,上爲Y軸的正方向,同理,數學座標系中角度也是逆時針爲正方向,如下圖:
- 屏幕座標系
Android中屏幕的座標系定義是以左上角爲起點,右邊爲X軸正方向,下方爲Y軸正方向,如下圖:
對應的角度方向,也是順時針爲正方向
貼上一個屏幕,大概就是下面這樣
二、View的座標系
View的座標系統是相對於父控件而言的
通常有以下幾個方法,
getTop()
獲取View左上角距父View頂部的距離
getLeft()
獲取View左上角距父View左側的距離
getBottom()
獲取View右下角距父View頂部的距離
getRight()
獲取View右下角距父View左側的距離
怎麼理解呢,我們直接通過Demo來驗證,先寫一個佈局文件如下:
activity_ui_custom_location.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<LinearLayout
android:id="@+id/ll_view"
android:layout_width="300dp"
android:layout_height="300dp"
android:background="@color/colorAccent">
<View
android:id="@+id/view"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="@color/colorPrimary" />
</LinearLayout>
</RelativeLayout>
上面的xml佈局文件預覽如下:
通過上面的xml文件我們可以分析出來,B(View)視圖的父View是A(LinearLayout),而A(LinearLayout)的父佈局又是C(RelativeLayout)
我們現在分別來獲取A和B的座標位置:
View mView = findViewById(R.id.view);
LinearLayout mLlView = findViewById(R.id.ll_view);
mView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
mView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
int viewLeft = mView.getLeft();
int viewTop = mView.getTop();
int viewRight = mView.getRight();
int viewBottom = mView.getBottom();
LogUtil.d(TAG + "--view viewLeft=" + viewLeft);
LogUtil.d(TAG + "--view viewTop=" + viewTop);
LogUtil.d(TAG + "--view viewRight=" + viewRight);
LogUtil.d(TAG + "--view viewBottom=" + viewBottom);
}
});
mLlView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
mLlView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
int llViewLeft = mLlView.getLeft();
int llViewTop = mLlView.getTop();
int llViewRight = mLlView.getRight();
int llViewBottom = mLlView.getBottom();
LogUtil.d(TAG + "--view llViewLeft=" + llViewLeft);
LogUtil.d(TAG + "--view llViewTop=" + llViewTop);
LogUtil.d(TAG + "--view llViewRight=" + llViewRight);
LogUtil.d(TAG + "--view llViewBottom=" + llViewBottom);
}
});
結果:
我們看到B(View)獲取的top
和left
爲0,由此可以推斷出View獲取的座標位置是基於父佈局來的,因爲B的左上角剛好是其父類的左上角,所以獲取數據爲0。如果我們B居中,如下:
再次獲取座標位置結果如下:
分析結果能得出如下結論:
三.MotionEvent中 get 和 getRaw 的區別
我們同樣先通過Demo來得出結論,我們直接拿上面的demo進行演示,
mView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
float getX = event.getX();
float getRawX = event.getRawX();
float getY = event.getY();
float getRawY = event.getRawY();
LogUtil.d(TAG + "--setOnTouchListener getX=" + getX + ",getRawX=" + getRawX);
LogUtil.d(TAG + "--setOnTouchListener getY=" + getY + ",getRawY=" + getRawY);
return false;
}
});
我們儘量的點擊視圖B的左上角位置,得到如下結果:
我們可以看到
getX
、getY
的值趨近於零(手指點擊最左上角得到的結果應該是0,0)
getRawX
、getRawY
的值對比上面的結果,肯定不是相對於父類A的,而是相對於屏幕的座標位置。
基於以上結果,大致得出以下結論:
實際座標出發點是同一點,爲了區分黃線分別右移和下移了一點,圖比較粗糙,清楚就好。
四、Android中角度和弧度
在後續的自定義View中,一些複雜的圖形需要各種數學上的計算,簡單舉個例子,我們在自定義圓形進度條或者自定義一個鐘錶的時候,就涉及到角度和弧度的概念,所以我們提前對Android中的角度和弧度有一個認識。
首先看看,角度和弧度在圓上如何表示:
角度
弧度
由上面兩個圖可以得出角度和弧度的定義:
名稱 | 定義 |
---|---|
角度 | 兩條射線從圓心向圓周射出,形成一個夾角和夾角正對的一段弧。當這段弧長正好等於圓周長的360分之一時,兩條射線的夾角的大小爲1度. |
弧度 | 兩條射線從圓心向圓周射出,形成一個夾角和夾角正對的一段弧。當這段弧長正好等於圓的半徑時,兩條射線的夾角大小爲1弧度. |
爲什麼對角的描述有角度和弧度兩種,因爲二者進制不同,角度是60進制,而弧度是十進制,在自定義View計算的時候可以要根據不同的數值進行轉換。
4.1、角度和弧度的換算方式
圓一週角度爲360°,弧度爲2π
所以 360° = 2π --------------------------> 180° = π
- 1° = π/180
- 1弧度 = 180/π
五、顏色
5.1、簡單顏色介紹
Android中支持的顏色模式
顏色模式 | 備註 |
---|---|
ARGB8888 | 四通道高精度(32位) |
ARGB4444 | 四通道低精度(16位) |
RGB565 | 屏幕默認模式(16位) |
Alpha8 | 僅有透明通道(8位) |
字母表示通道類型,數值表示該類型用多少位二進制來表示
如ARGB8888表示有四個通道,每個對應的通道用8位二進制表示
RGB565表示三個通道,每個對應通道分別使用5、6、5位二進制表示
注意:我們常用的是ARGB8888和ARGB4444,而在所有的安卓設備屏幕上默認的模式都是RGB565,請留意這一點
以ARGB8888爲例介紹顏色定義:
類型 | 解釋 | 0(0x00) | 255(0xff) |
---|---|---|---|
A(Alpha) | 透明度 | 透明 | 不透明 |
R(Red) | 紅色 | 無色 | 紅色 |
G(Green) | 綠色 | 無色 | 綠色 |
B(Blue) | 藍色 | 無色 | 藍色 |
-
其中 A R G B 的取值範圍均爲0(0000 0000)- 255(1111 1111)
-
A 從0x00到0xff表示從透明到不透明。
-
RGB 從0x00到0xff表示顏色從淺到深。
我們在代碼中顏色設置就可以如下定義:
總結
簡單介紹了一下自定義view一些基礎概念和知識點,本文感謝
自定義View,這是自定義view第一篇,後續會一步步探索,也會通過一些實戰來鞏固,整理也是學習過程,文章內容會盡量整的詳細一些,感謝你的閱讀,如果文中有錯誤之處,接受批評和指點。