自定義View知識體系

自定義View簡介

在Android原生控件無法滿足需求的情況下,但是又需要實現一些特殊效果的時候該怎麼辦呢?這個時候就可以通過自定義View去實現。因此自定義View是對於Android工程師來說無疑是比較重要的技能。今天我會針對自定義View的一些知識作講解,水平有限,不對的地方望批評交流。

自定義View分類

自定義View本質上其實就是通過Java的繼承特性去擴展特定需求,且大家都知道Android中的控件可以大體上分爲View與ViewGroup(注意ViewGroup本質上也是View)。例如:TextView是通過繼承View實現,LinearLayout是通過繼承ViewGroup實現。那麼自定義View的話,肯定是可以直接通過繼承View或者ViewGroup去實現。但是一般情況下優先考慮繼承已經控件去實現自定義View,那麼就有以下幾種分類:

1.繼承View
這種方式主要用來實現一些不規則效果,即通過onDraw繪製控件內容,並且如果有交互需求的話,通過onTouchEvent方法去處理觸摸事件。例如:QQ的小紅點

注意問題:需自行支持wrap_content與padding

2.繼承特定的View
這種方式一般用於擴展已有View的功能,根據需要覆寫相關的方法,重寫邏輯。例如:自定義View繼承TextView實現圖文混排控件

3.繼承ViewGroup
這種方式側重於控件元素的佈局排列,線性佈局採用的是現行排列控件,相對佈局採用的是相對方式排列控件。那麼假設我們需要特定的排列規則系統並沒有提供控件,我們就可以通過自定View繼承ViewGroup實現。作爲ViewGroup,其他核心實現就是控件的測量onMeasure、控件排列規則onLayout。

4.繼承特定的ViewGroup
這種方式傾向於用某種排列方式組合特定的子控件,例如咱們可以通過繼承線性佈局並且向其中添加一定數量的子元素水平均勻分佈作爲主頁面的底部選擇控件。

自定義View知識點整理

1.View的工作原理
理解View的三大流程
參考:View的工作原理

2.View的事件體系
包括View的位置參數與View的觸摸事件流程,即事件分發機制
參考:View的事件體系

3.動畫相關
View動畫Animation:包括補間動畫與幀動畫
屬性動畫:ObjectAnimator、ValueAnimator
貝塞爾曲線:Path#quadTo()和Path#cubicTo()
屬性動畫的插值器TimeInterpolator與估值器TypeEvaluator

4.畫布Canvas
繪製顏色 drawColor, drawRGB, drawARGB
繪製基本形狀 drawPoint, drawPoints, drawLine, drawLines, drawRect, drawRoundRect, drawOval, drawCircle, drawArc
繪製圖片 drawBitmap, drawPicture
繪製文本 drawText, drawPosText, drawTextOnPath
繪製路徑 drawPath 繪製貝塞爾曲線時也需要用到該函數
頂點操作 drawVertices, drawBitmapMesh 通過對頂點操作可以使圖像形變,drawVertices直接對畫布作用、 drawBitmapMesh只對繪製的Bitmap作用
畫布剪裁 clipPath, clipRect 設置畫布的顯示區域
畫布快照 save, restore, saveLayerXxx, restoreToCount, getSaveCount 依次爲 保存當前狀態、 回滾到上一次保存的狀態、 保存圖層狀態、 回滾到指定狀態、 獲取保存次數
畫布變換 translate, scale, rotate, skew 依次爲 位移、縮放、 旋轉、錯切
Matrix(矩陣) getMatrix, setMatrix, concat 實際上畫布的位移,縮放等操作的都是圖像矩陣Matrix, 只不過Matrix比較難以理解和使用,故封裝了一些常用的方法。

5.Paint
ColorMatrix setColorFilter 顏色矩陣 濾鏡效果
setXfermode 圖形混合模式

6.Shader
BitmapShader 類:位圖渲染器
LinearGradient 類:線性漸變
RadialGradient 類:放射漸變
SweepGradient 類:掃射漸變
ComposeShader 類:組合渲染器

6.Path
addArc(RectF oval, float startAngle, float sweepAngle)
繪製弧線,配合Paint的Style可以實現不同的填充效果
addCircle(float x, float y, float radius, Path.Direction dir)
繪製圓形,其中第dir參數用來指定繪製時是順時針還是逆時針
addOval(RectF oval, Path.Direction dir)
繪製橢圓形,其中 oval作爲橢圓的外切矩形區域
addRect(RectF rect, Path.Direction dir)
繪製矩形
addRoundRect(RectF rect, float rx, float ry, Path.Direction dir)
繪製圓角矩形
lineTo(float x, float y)
繪製直線
addPath(Path src)
添加一個新的Path到當前Path
arcTo(RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)
與addArc方法相似,但也有區別,下文細述。
quadTo(float x1, float y1, float x2, float y2)
繪製二次貝塞爾曲線,其中 (x1,y1)爲控制點,(x2,y2)爲終點
cubicTo(float x1, float y1, float x2, float y2, float x3, float y3)
繪製三次貝塞爾曲線,其中(x1,y1),(x2,y2)爲控制點,(x3,y3)爲終點

r開頭的方法是基於當前繪製開始點的offest,比如當前paint位於 (100,100)處,則使用rLineTo(100,100)方法繪製出來的直線是從(100,100)到(200,200)的一條直接,由此可見rXXX方法方便用來基於之前的繪製作連續繪製

Path.op方法
此方法用於對兩個Path對象做相應的運算組合(combine)

6.PathMeasure
解析Path對象並可截取片段,通過這個類可以實現路徑動畫效果
路徑動畫

自定義View整體流程

1.需求分析:分析你所需要實現的自定義控件的效果,包括UI效果與用戶交互效果 2.實現方式:選擇自定義控件的方式,根據自定義View的效果選擇合適的方式實現。首先確定該自定義控件是屬於組合類或者偏向於效果交互類,選擇繼承View或者ViewGroup。再者考慮是否可基於現有系統原生控件進行修改擴展實現 3.代碼實現:自定義屬性attr、初始化(Path、Paint、Canvas緩存、控件屬性、相關邏輯變量等)、測量onMeasure、佈局onLayout、界面繪製onDraw。如果有用戶交互的話,則在onTouchEvent中實現交互邏輯