涉及知識
繪制過程涉及到主要方法
類別 | API | 描述 |
---|---|---|
布局 | onMeasure | 測量View與Child View的大小 |
onLayout | 確定Child View的位置 | |
onSizeChanged | 確定View的大小 | |
繪制 | onDraw | 實際繪制View的內(nèi)容 |
事件處理 | onTouchEvent | 處理屏幕觸摸事件 |
重繪 | invalidate | 調(diào)用onDraw方法,重繪View中變化的部分 |
Canvas涉及到主要方法
類別 | API | 描述 |
---|---|---|
繪制圖形 | drawPoint、drawPoints、drawLine、drawLines、drawRect、drawRoundRect、drawOval、drawCircle、drawArc | 依次為繪制點、直線、矩形、圓角矩形、橢圓、圓、散形 |
繪制文本 | drawText、drawPosText、drawTextOnPath | 依次為繪制文字、指定每個字符位置繪制文字、根據(jù)路徑繪制文字 |
畫布變換 | translate、scale、rotate、skew | 依次為平移、縮放、旋轉(zhuǎn)、傾斜(錯切) |
畫布裁剪 | clipPath、clipRect、clipRegion | 依次為按路徑、按矩形、按區(qū)域或?qū)Ξ嫴歼M行裁剪 |
Paint涉及到主要方法
類別 | API | 描述 |
---|---|---|
顏色 | setColor、setARGB、setAlpha | 依次為設(shè)置畫筆顏色、透明度 |
類型 | setStyle | 填充(FILL),描邊(STROKE),填充加描邊(FLIL_STROKE) |
抗鋸齒 | setAntiAlias | 畫筆是否抗鋸齒 |
字體大小 | setTextSize | 設(shè)置字體到大小 |
字體測量 | getFontMetrics()、getFontMetricsInt() | 返回字體測量,返回依次為float、int |
文字寬度 | measureText | 返回文字到寬度 |
文字對齊方式 | setTextAlign | 左對齊(LEFT)、居中對齊(CENTER)、右對齊(RIGHT) |
寬度 | setStrokeWidth | 設(shè)置畫筆寬度 |
筆鋒 | setStrokeCap | 默認(BUTT),半圓形(ROUND),方形(SQUARE) |
(注:因API較多,只列出常用到方法,想了解更多,請查看官方文檔)
一、坐標(biāo)系
1、屏幕坐標(biāo)系
屏幕坐標(biāo)系以手機屏幕到左上角為坐標(biāo)原點,過原點的水平直線為X軸,向右為正方向;過原點的垂線為Y軸,向下為正方向;
2、View坐標(biāo)系
View坐標(biāo)系以父視圖到左上角為坐標(biāo)原點,過原點的水平直線為X軸,向右為正方向;過原點的垂線為Y軸,向下為正方向
View內(nèi)部擁有四個函數(shù),用于獲取View到位置
getTop(); //View的頂邊到其Parent View的頂邊的距離,即View的頂邊與View坐標(biāo)系的X軸之間的距離
getLeft(); //View的左邊到其Parent View的左邊的距離,即View的左邊與View坐標(biāo)系的Y軸之間的距離
getBottom(); //View的底邊到其Parent View的頂邊的距離,即View的底邊與View坐標(biāo)系的X軸之間的距離
getRight(); //View的右邊到其Parent View的左邊的距離,即View的右邊與View坐標(biāo)系的Y軸之間的距離
如圖所示
二、繪制過程
1、自定義屬性
參考Android 自定義View二(深入了解自定義屬性attrs.xml)
2、onMeasure
參考Android 自定義View 一(初體驗onDraw(),自定義屬性,onMeasue()方法,測量換行)
3、onLayout
用于確定View以及其子View的布局位置,在ViewGroup中,當(dāng)位置被確定后,它在onLayout中會遍歷所有到child并調(diào)用其layout,然后layout內(nèi)部會再調(diào)用child到onLayout確定child view到布局位置
layout放法如下
public void layout(int l, int t, int r, int b) {
····
int oldL = mLeft;
int oldT = mTop;
int oldB = mBottom;
int oldR = mRight;
····
for (int i = 0; i < numListeners; ++i) {
listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
}
}
}
·····
}
mLeft,mTop,mBottom,mRight四個參數(shù)分別通過getLeft(),getTop(),getBottom(),getRight(),四個函數(shù)獲得,這一組old值會在位置改變時,調(diào)用onLayoutChanges時使用到
4、onSizeChanged
如其名,在View大小改變是調(diào)用此函數(shù),用于確定View的大小。至于View大小為什么會改變,因為View的大小不僅由本身確定,同事還受父View到影響
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
這里到w、h就是確定后到高寬值,如果查看View中的onLayoutChange也會看到類似的情況,擁有l(wèi), t, r, b, oldL, oldT, oldR, oldB,新舊兩組參數(shù)
5、onDraw
onDraw是View的繪制部分,給了我們一張空白的畫布,使用Canvas進行繪制。也是后面幾篇文章所要分享的內(nèi)容。
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
6、onTouchEvent
@Override
public boolean onTouchEvent(MotionEvent event) {
return super.onTouchEvent(event);
}
當(dāng)返回true時,說明該View消耗了觸摸事件,后續(xù)到觸摸事件由它來進行處理。返回false時,說明該View對觸摸事件不感興趣,事件繼續(xù)傳遞下去。觸屏事件類型被封裝在MotionEvent中,MotionEvent提供了很多類型事件,主要關(guān)系以下幾種類型:
事件類型 | 描述 |
---|---|
ACTION_DOWN | 手指按下 |
ACTION_MOVE | 手指移動 |
ACTION_UP | 手指抬起 |
在MotionEvent中有兩組可以獲得觸摸位置到函數(shù)
event.getX(); //觸摸點相對于View坐標(biāo)系的X坐標(biāo)
event.getY(); //觸摸點相對于View坐標(biāo)系的Y坐標(biāo)
event.getRawX(); //觸摸點相對于屏幕坐標(biāo)系的X坐標(biāo)
event.getRawY(); //觸摸點相對于屏幕坐標(biāo)系的Y坐標(biāo)
如圖所示:
onWindowFocusChanged運行于onMeasure與onLayout之后,可以獲取到正確的width、height、top、left等屬性值。