這是一篇總結性地文章凡纳,內容來自扔物線文章以及網易公開課,本文是自己對文章的總結
一、View的坐標系
每一個子View都有一個自己的坐標系领铐,并且互不影響悯森,坐標系的原點是View的左上角,遵循右正左負绪撵,下正上負
如這張圖所示瓢姻,在左上定點為畫布的原點,圓心的左邊是(300,300)
二音诈、canvas的作用
1.canvas可以指定繪制的位置幻碱,以及繪制什么樣的圖層
canvas.drawColor() 在整個繪制層上繪制一層背景色
三绎狭、Paint負責繪制的風格
繪制的顏色,抗鋸齒褥傍,繪制線條的方式儡嘶,實心還是空心等等和風格相關的都是由paint來做的
Paint.setAntiAlias(boolean aa) 設置抗鋸齒開關
Paint.setStyle(Paint.Style.STROKE) 畫出圖形的線條 不會填充整個圖形
Paint.setStrokeCap(cap) 設置線條端點形狀
Paint. setShader 設置著色器
Paint.setColorFilter 設置顏色的過濾效果 比如加濾鏡
Paint.setStrokeJoin 設置線條拐角的方式
Paint.setDither(boolean dither) 加入抖動效果有規(guī)律地擾亂圖像來讓圖像對于肉眼更加真實
Paint.setFilterBitmap(filterBitmap)優(yōu)化圖像放大后的效果,消除馬賽克
Paint.setPathEffect 圖像外圍輪廓線的效果
Paint.setShadowLayer 給繪制的內容加一層陰影 BlurMaskFilter 模糊效果
1. Paint.setStrokeCap(cap)效果示意圖
2. Paint.setFilterBitmap(true)效果示意圖
左邊是未開啟優(yōu)化的恍风,右邊是開啟優(yōu)化的蹦狂,可以看到少了許多馬賽克的效果
3. Paint.setStrokeJoin效果示意圖
4.使用著色器可以實現(xiàn)一種規(guī)律性的變化。著色器分為三類 線性漸變new LinearGradient朋贬,從中心進行輻射漸變RadialGradient,像雷達
一樣掃描的漸變SweepGradient凯楔, 使用圖像來圖形上色 BitmapShader,將多個著色器組合起來使用的ComposeShader
線性的著色器示例
/**
* 1.線性渲染,LinearGradient(float x0, float y0, float x1, float y1, @NonNull @ColorInt int colors[], @Nullable float positions[], @NonNull TileMode tile)
* (x0,y0):漸變起始點坐標
* (x1,y1):漸變結束點坐標
* color0:漸變開始點顏色,16進制的顏色表示锦募,必須要帶有透明度
* color1:漸變結束顏色
* colors:漸變數(shù)組
* positions:位置數(shù)組摆屯,position的取值范圍[0,1],作用是指定某個位置的顏色值,如果傳null糠亩,漸變就線性變化虐骑。
* tile:用于指定控件區(qū)域大于指定的漸變區(qū)域時,空白區(qū)域的顏色填充方法
*/
mShader = new LinearGradient(0, 0, 500, 500, new int[]{Color.RED, Color.BLUE, Color.GREEN}, new float[]{0.f,0.7f,1}, Shader.TileMode.REPEAT);
mPaint.setShader(mShader);
canvas.drawRect(0,0,1000,1000, mPaint);
環(huán)形的著色器示例
/* 環(huán)形渲染削解,RadialGradient(float centerX, float centerY, float radius, @ColorInt int colors[], @Nullable float stops[], TileMode tileMode)
* centerX ,centerY:shader的中心坐標富弦,開始漸變的坐標
* radius:漸變的半徑
* centerColor,edgeColor:中心點漸變顏色,邊界的漸變顏色
* colors:漸變顏色數(shù)組
* stoops:漸變位置數(shù)組氛驮,類似掃描漸變的positions數(shù)組腕柜,取值[0,1],中心點為0,半徑到達位置為1.0f
* tileMode:shader未覆蓋以外的填充模式矫废。
*/
mShader = new RadialGradient(250, 250, 250, new int[]{Color.GREEN, Color.YELLOW, Color.RED}, null, Shader.TileMode.CLAMP);
mPaint.setShader(mShader);
canvas.drawCircle(250, 250, 250, mPaint);
位圖的著色器示例
/**
* 位圖渲染盏缤,BitmapShader(@NonNull Bitmap bitmap, @NonNull TileMode tileX, @NonNull TileMode tileY)
* Bitmap:構造shader使用的bitmap
* tileX:X軸方向的TileMode
* tileY:Y軸方向的TileMode
REPEAT, 繪制區(qū)域超過渲染區(qū)域的部分,重復排版
CLAMP蓖扑, 繪制區(qū)域超過渲染區(qū)域的部分唉铜,會以最后一個像素拉伸排版
MIRROR, 繪制區(qū)域超過渲染區(qū)域的部分,鏡像翻轉排版
*/
mShader = new BitmapShader(mBitmap, Shader.TileMode.REPEAT, Shader.TileMode.MIRROR);
mPaint.setShader(mShader);
canvas.drawRect(0,0,500, 500, mPaint);
組合的著色器示例
/**
* 組合渲染律杠,
* ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB, Xfermode mode)
* ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB, PorterDuff.Mode mode)
* shaderA,shaderB:要混合的兩種shader
* Xfermode mode: 組合兩種shader顏色的模式
* PorterDuff.Mode mode: 組合兩種shader顏色的模式
*/
BitmapShader bitmapShader = new BitmapShader(mBitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
LinearGradient linearGradient = new LinearGradient(0, 0, 1000, 1600, new int[]{Color.RED, Color.GREEN, Color.BLUE}, null, Shader.TileMode.CLAMP);
mShader = new ComposeShader(bitmapShader, linearGradient, PorterDuff.Mode.MULTIPLY);
mPaint.setShader(mShader);
canvas.drawCircle(250, 250, 250, mPaint);
三潭流、Canvas重點API
drawArc :畫扇形
drawPath(Path,Paint):畫自定義的圖形
drawTextOnPath:沿著一趟線繪制文字
1.對于drawPath需要傳入path對象。path對象又有幾種屬性柜去。
addXXX 表示添加某圖形
quadTo:貝塞爾曲線
moveTo:將圓點移動到指定的位置灰嫉,不管畫什么圖形都是從當前位置開始畫的,通過moveTo可以指定畫筆起始的位置嗓奢。
close() 自動封閉讼撒,假設畫了三角形的兩邊后直接調用該方法,會自動將兩點連接起來形成封閉。
setFillType(Path.FillType ft) 設置填充方式
2.drawText難點
1.drawText指定的x根盒,y是要繪制的文字左下角的坐標钳幅,縱坐標y代表文字的基線
2.可以使用StaticLayout來實現(xiàn)繪制文字的自動換行
- setTypeface設置字體
- setStrikeThruText刪除線setUnderlineText下劃線
- setLetterSpacing字符的間距
- setFontFeatureSettings使用css的方式設置字體
- setTextAlign對其方式
- setTextLocale設置繪制文字的地域文字類型。大陸簡體 臺灣繁體
- getFontSpacing獲取推薦的行距炎滞,可以在換行繪制時使用
canvas.drawText(texts[1], 100, 150 + paint.getFontSpacing, paint);
4.canvas的裁切
繪制的內容超出這個范圍會被裁切掉敢艰,使用clipRect方法。clipPath
5.保存canvas的一次繪制狀態(tài)
canvas.save厂榛, canvas.restore盖矫。幾何變化一定要配合save和restore來配合使用。否則將后續(xù)繪制也受之前的影響
canvas的幾何變換
canvas的幾何變換代碼執(zhí)行順序是倒序的击奶,如果想要先旋轉再平移辈双,那么平移代碼要寫在最上面,再寫旋轉的代碼柜砾。translate湃望,scale,rotate痰驱,skew
6.canvas的平移
使用translate方法讓中心點平移到某個位置,由于canvas的幾何變換是反著的证芭,所以如果要先平移到一個點,再移動回原點要先寫移動回原點的代碼担映,再寫移動到其他位置的代碼废士。
7.使用matris矩陣來變換
post..方法代表在前面插入,也就是變換代碼是順序執(zhí)行的
per..方法是往后邊的代碼插入蝇完,也就是和canvas的變換順序官硝,會插入到其他變換代碼的后面。
四短蜕、使用Camera來實現(xiàn)三維旋轉
1.camera.save/restore/applytoCanvas
camera的操作是在圖像的原點(0,0)進行的氢架,因此使用camera變化是不對稱的,如果想要在圖形的中心點進行變化朋魔,需要配合canvas的translate方法將canvas移動到中心點進行變化岖研,然后再移動回去。因為camera是不支持設置軸心的警检,軸心永遠是(0,0點)孙援。
2.使用setLocation來將相機的位置向后移動
相機后移投影的圖像變小。一般情況不需要移動x扇雕,y 只需要移動z軸赃磨。因為相機是在z軸上。
camera.setLocation(0, 0, newZ);
**3.camera的旋轉正方向
View繪制的過程
1.新繪制的總是會覆蓋之前繪制的內容
2.View的繪制過程是從drawBackground(不能重寫)洼裤,onDraw繪制主題,dispatchDraw繪制子view,drawForeground繪制前景色腮鞍,而這些都是由draw方法觸發(fā)的
3.如果是直接繼承view值骇,super.onDraw并沒有什么用,因為onDraw本身就是空實現(xiàn)
4.ViewGroup在通過onDraw繪制完自身后移国,會通過onDispatchDraw方法繪制子View
5.ViewGroup默認會跳過draw方法而直接執(zhí)行dispatchDraw吱瘩,如果想讓它繪制自身,使用setWillNotDraw(false)來執(zhí)行完整的繪制流程