Android 繪圖——Canvas

鋸齒流沙發表於2017-12-26

Canvas簡介

Canvas也就是Android中的畫布,它儲存了一些列的draw方法,你可以是用Canvas繪製圖形、文字和點陣圖等,其功能可謂是十分的強大,幾乎可以繪製所有的影象和文字。既然Canvas功能如此強大,其豐富了Android的圖形,也是Android圖形學不可或缺的類,而學習和熟練Canvas,可謂是學習Android UI的重點之一,接下來我們開始學習Canvas的API。

Canvas繪圖

既然Canvas提供了繪製圖形的功能,那麼看下其對應的API有那些。

繪製直線
public class CanvasView extends View {
    Paint paint;
    public CanvasView(Context context) {
        this(context,null);
    }

    public CanvasView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        paint = new Paint();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        paint.setColor(Color.RED);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(5);
        canvas.drawLine(0, 0, 100, 100, paint);
    }
}
複製程式碼

使用陣列,繪製直線

float []pts = {0,0,100,100,200,200,300,300};
canvas.drawLines(pts, paint);
複製程式碼

先繪製(0,0)到(100,100)的直線,然後繪製(200,200)到(300,300)的直線。

效果圖.png

定義陣列,也可以使用下面語句來繪製直線

drawLines(@Size(multiple = 4) @NonNull float[] pts, int offset, int count, @NonNull Paint paint)
複製程式碼

pts:座標陣列 offset:設定線的間隔距離 count:繪製直線的條數 paint:畫筆

drawPoint

繪製點:

drawPoint(float x, float y, @NonNull Paint paint)
複製程式碼

繪製多個點:

float []pts = {0,0,100,100,200,200,300,300};
canvas.drawPoints(pts, paint);
複製程式碼

效果圖.png

drawRect

繪製矩形,矩形區域有兩種表示方式:Rect和RectF,Rect表示int型別,RectF表示float型別。

RectF r = new RectF(100, 100, 400, 500);
canvas.drawRect(r, paint);
複製程式碼

效果圖.png

也可以如下表示:

drawRect(float left, float top, float right, float bottom, @NonNull Paint paint)
複製程式碼
drawRoundRect

使用drawRoundRect,繪製圓角矩形

drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint)

rx:x軸的圓角半徑大小 ry:y軸的圓角半徑大小

RectF r = new RectF(100, 100, 400, 500);
canvas.drawRoundRect(r, 100, 100, paint);
複製程式碼

效果圖.png

drawCircle

繪製圓 :

drawCircle(float cx, float cy, float radius, @NonNull Paint paint)
複製程式碼

cx、cy:圓心座標 radius:半徑

canvas.drawCircle(300, 300, 200, paint);
複製程式碼

效果圖.png

drawOval

使用drawOval函式繪製橢圓

drawOval(@NonNull RectF oval, @NonNull Paint paint) oval:定義的矩形 paint:畫筆

除了上述方法引數,可以使用以下方法引數:

drawOval(float left, float top, float right, float bottom, @NonNull Paint paint)

之所以提供一個矩形區域,是因為該橢圓是矩形的內切圓。

RectF r = new RectF(100, 100, 400, 500);
canvas.drawRect(r, paint);
canvas.drawOval(r, paint);
複製程式碼

效果圖.png

drawArc

使用drawArc方法繪製扇形圖。

drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter,@NonNull Paint paint)
複製程式碼

oval:矩形,該扇形是在矩形區域內繪製的,而且圍繞著矩形的中心點來繪製。 startAngle:開始角度,相對X軸正方向 sweepAngle:畫多少角度的弧度 useCenter:false表示只有一個純弧線,true表示閉合的邊 paint:畫筆

RectF r = new RectF(100, 100, 400, 500);
canvas.drawRect(r, paint);
canvas.drawArc(r, 0, 90, true, paint);//順時針旋轉90度
複製程式碼

效果圖.png

drawPath

使用drawPath來繪製路徑,更加靈活的繪製出各式各樣的圖形。繪製路徑,我們需要理解以下幾個方法: 1)moveTo(float x, float y):畫筆落筆的位置 2)lineTo(float x, float y):畫筆移動的到(x,y)座標,並沿著繪製出路徑。 3)cubicTo(float x1, float y1, float x2, float y2,float x3, float y3):實現貝塞爾曲線路徑, (x1,y1) 為控制點,(x2,y2)為控制點,(x3,y3) 為結束點。 4)quadTo(float x1, float y1, float x2, float y2):也是繪製貝塞爾曲線,即橢圓曲線。(x1,y1)控制點,(x2,y2)結束點。 5)arcTo:繪製弧線。

Path path = new Path();
path.moveTo(100, 100);
path.lineTo(200, 100);
path.cubicTo(250, 200, 350, 300, 450, 400);
path.close();
canvas.drawPath(path, paint);
複製程式碼

效果圖.png

弧線
RectF r = new RectF(100, 100, 400, 500);
Path path = new Path();
path.addArc(r, 30, 70);
canvas.drawPath(path, paint);
複製程式碼
圓角矩形路徑
RectF r = new RectF(100, 100, 400, 500);
Path path = new Path();
float radii[] = {//左上角開始,順時針依次的角度
                         10,//x1
                         10,//y1
                         10,//x2
                         10,//y2
                         10,//x3
                         10,//y30
                         50,//x4
                         60};//y4
path.addRoundRect(r, radii, Path.Direction.CCW);
canvas.drawPath(path, paint);
複製程式碼

效果圖.png

Canvas變換技巧

Canvas變換包括: 1)平移(Translate) 2)縮放(Scale) 3)旋轉(Rotate) 4)斜拉畫布(Skew) 5)裁剪畫布(clip)

平移
RectF r = new RectF(0, 0, 400, 500);
canvas.drawRect(r, paint);
paint.setColor(Color.BLUE);
//將畫布平移
canvas.translate(50, 50);
canvas.drawRect(r, paint);
複製程式碼

效果圖.png

上圖中畫布平移了,藍色的矩形平移了,但是紅色的矩形沒有平移,是因為當canvas執行drawXXX的時候就會新建一個新的畫布圖層,而平移知識平移新的圖層。

RectF r = new RectF(0, 0, 400, 500);
canvas.drawRect(r, paint);
paint.setColor(Color.BLUE);
 //將畫布平移
canvas.translate(50, 50);
canvas.drawRect(r, paint);
RectF r2 = new RectF(0, 0, 400, 500);
paint.setColor(Color.GREEN);
canvas.drawRect(r2, paint);
複製程式碼

效果圖.png

從上圖中可以看到綠色矩形覆蓋了藍色的矩形,雖然draw的時候,新建了一個畫布圖層,但是還是會沿用之前設定的平移變換。不可逆的。解決這種情況需要使用save和restore來解決。

縮放

scale(float sx, float sy)

sx、sy:分別對x/y方向的一個縮放係數,畫布的縮放會導致裡面所有的繪製的東西都會有一個縮放效果。

RectF r = new RectF(0, 0, 400, 500);
canvas.drawRect(r, paint);
paint.setColor(Color.BLUE);
canvas.scale(1.5f, 0.5f);
canvas.drawRect(r, paint);
複製程式碼

效果圖.png

旋轉

rotate(float degrees),degrees:旋轉角度,順時針旋轉 rotate(float degrees, float px, float py),degrees旋轉角度,(px,py)旋轉中心點座標

RectF r = new RectF(200, 200, 400, 500);
canvas.drawRect(r, paint);
paint.setColor(Color.BLUE);
canvas.rotate(45);
canvas.drawRect(r, paint);
複製程式碼
斜拉畫布

skew(float sx, float sy):sx,sy傾斜度

RectF r = new RectF(200, 200, 400, 500);
canvas.drawRect(r, paint);
paint.setColor(Color.BLUE);
canvas.skew(1.73f, 0);
canvas.drawRect(r, paint);
複製程式碼

效果圖.png

裁剪畫布

clipRect(@NonNull Rect rect) rect:裁剪的矩形區域

RectF r = new RectF(200, 200, 400, 500);
canvas.drawRect(r, paint);
paint.setColor(Color.BLUE);
canvas.clipRect(new Rect(250, 250, 300, 400));
canvas.drawColor(Color.YELLOW);
複製程式碼

效果圖.png

理解canvas

Canvas畫布的正確的理解: 1)當canvas執行drawXXX的時候就會新建一個新的畫布圖層

2)雖然後面新建了一個畫布圖層,但是還是會沿用之前設定的平移變換。不可逆的。(save和restore來解決)

相關文章