Android自定義View學習四---Canvas畫布操作

Canvas之畫布操作

內容來自:安卓自定義View進階-Canvas之畫布操作

基本操作

位移

translate是座標系的移動,位移是基於當前位置移動,而不是每次基於屏幕左上角的(0,0)點移動

        // 繪製矩形
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.STROKE);
        canvas.drawRect(new Rect(0, 0, 200, 200), mPaint);

        // 在座標原點繪製一個黑色圓形
        mPaint.setColor(Color.BLACK);
        mPaint.setStyle(Paint.Style.FILL);
        canvas.translate(200, 200);
        canvas.drawCircle(100, 100, 100, mPaint);

        // 在座標原點繪製一個藍色圓形
        mPaint.setColor(Color.BLUE);
        canvas.translate(200,200);
        canvas.drawCircle(0,0,100,mPaint);

位移

縮放(scale)

縮放提供了兩個方法,如下:

public void scale (float sx, float sy)

public final void scale (float sx, float sy, float px, float py)

縮放的中心默認爲座標原點,而縮放中心軸就是座標軸,第二個方法的pxpy,用來控制縮放中心位置

// 將座標系原點移動到畫布正中心
canvas.translate(mWidth / 2, mHeight / 2);

RectF rect = new RectF(0,-400,400,0);   // 矩形區域

mPaint.setColor(Color.BLACK);           // 繪製黑色矩形
canvas.drawRect(rect,mPaint);

canvas.scale(0.5f,0.5f);                // 畫布縮放

mPaint.setColor(Color.BLUE);            // 繪製藍色矩形
canvas.drawRect(rect,mPaint);

縮放01

使用第二種方法讓縮放中心位置稍微改變一下,如下:

// 將座標系原點移動到畫布正中心
canvas.translate(mWidth / 2, mHeight / 2);

RectF rect = new RectF(0,-400,400,0);   // 矩形區域

mPaint.setColor(Color.BLACK);           // 繪製黑色矩形
canvas.drawRect(rect,mPaint);

canvas.scale(0.5f,0.5f,200,0);          // 畫布縮放  <-- 縮放中心向右偏移了200個單位

mPaint.setColor(Color.BLUE);            // 繪製藍色矩形
canvas.drawRect(rect,mPaint);

縮放02

當縮放比例爲負數的時候會根據縮放中心軸進行翻轉

// 將座標系原點移動到畫布正中心
canvas.translate(mWidth / 2, mHeight / 2);

RectF rect = new RectF(0,-400,400,0);   // 矩形區域

mPaint.setColor(Color.BLACK);           // 繪製黑色矩形
canvas.drawRect(rect,mPaint);


canvas.scale(-0.5f,-0.5f);          // 畫布縮放

mPaint.setColor(Color.BLUE);            // 繪製藍色矩形
canvas.drawRect(rect,mPaint);

縮放03

和位移(translate)一樣,縮放也是可以疊加的,如下的例子:

        // 將座標系原點移動到畫布正中心
        canvas.translate(mWidth / 2, mHeight / 2);

        RectF rect = new RectF(-400,-400,400,400);

        for (int i = 0; i < 20; i++) {
            canvas.scale(0.9f, 0.9f);
            canvas.drawRect(rect, mPaint);
        }

縮放04

旋轉

旋轉提供了兩種方法:

public void rotate (float degrees)

public final void rotate (float degrees, float px, float py)

第二種方法多出來的兩個參數依舊是控制旋轉中心點的

默認的旋轉中心依舊是座標原點:

// 將座標系原點移動到畫布正中心
canvas.translate(mWidth / 2, mHeight / 2);

RectF rect = new RectF(0,-400,400,0);   // 矩形區域

mPaint.setColor(Color.BLACK);           // 繪製黑色矩形
canvas.drawRect(rect,mPaint);

canvas.rotate(180);                     // 旋轉180度 <-- 默認旋轉中心爲原點

mPaint.setColor(Color.BLUE);            // 繪製藍色矩形
canvas.drawRect(rect,mPaint);

旋轉01

改變旋轉中心位置:

// 將座標系原點移動到畫布正中心
canvas.translate(mWidth / 2, mHeight / 2);

RectF rect = new RectF(0,-400,400,0);   // 矩形區域

mPaint.setColor(Color.BLACK);           // 繪製黑色矩形
canvas.drawRect(rect,mPaint);

canvas.rotate(180,200,0);               // 旋轉180度 <-- 旋轉中心向右偏移200個單位

mPaint.setColor(Color.BLUE);            // 繪製藍色矩形
canvas.drawRect(rect,mPaint);

旋轉02

同樣旋轉也可以疊加

// 將座標系原點移動到畫布正中心
canvas.translate(mWidth / 2, mHeight / 2);

canvas.drawCircle(0,0,400,mPaint);          // 繪製兩個圓形
canvas.drawCircle(0,0,380,mPaint);

for (int i=0; i<=360; i+=10){               // 繪製圓形之間的連接線
   canvas.drawLine(0,380,0,400,mPaint);
   canvas.rotate(10);
}

旋轉03

skew

skew只提供了一種方法

public void skew (float sx, float sy)
  • sx - 將畫布在x方向上傾斜相應的角度,sx傾斜角度的tan
  • sy - 將畫布在y軸方向上傾斜相應的角度,sy爲傾斜角度的tan
// 將座標系原點移動到畫布正中心
canvas.translate(mWidth / 2, mHeight / 2);

RectF rect = new RectF(0,0,200,200);   // 矩形區域

mPaint.setColor(Color.BLACK);           // 繪製黑色矩形
canvas.drawRect(rect,mPaint);

canvas.skew(1,0);                       // 水平錯切 <- 45度

mPaint.setColor(Color.BLUE);            // 繪製藍色矩形
canvas.drawRect(rect,mPaint);

skew01

save和restore

我的理解,類似於iOS的CGContextSaveGStateCGContextRestoreGState

相關API 簡介
save 把當前的畫布的狀態進行保存,然後放入特定的棧中
saveLayerXxx 新建一個圖層,並放入特定的棧中
restore 把棧中最頂層的畫布狀態取出來,並按照這個狀態恢復當前的畫布
restoreToCount 彈出指定位置及其以上所有的狀態,並按照指定位置的狀態進行恢復
getSaveCount 獲取棧中內容的數量(即保存次數)

狀態棧

狀態棧可以存儲畫布狀態和圖層狀態

狀態棧

save

save 有兩種方法:

// 保存全部狀態
public int save ()

// 根據saveFlags參數保存一部分狀態
public int save (int saveFlags)

可以看到第二種方法比第一種多了一個saveFlags參數,使用這個參數可以只保存一部分狀態,更加靈活。saveFlags參數,參見下表

名稱 簡介
ALL_SAVE_FLAG 默認,保存全部狀態
CLIP_SAVE_FLAG 保存剪輯區
CLIP_TO_LAYER_SAVE_FLAG 剪裁區作爲圖層保存
FULL_COLOR_LAYER_SAVE_FLAG 保存圖層的全部色彩通道
HAS_ALPHA_LAYER_SAVE_FLAG 保存圖層的alpha(不透明度)通道
MATRIX_SAVE_FLAG 保存Matrix信息( translate, rotate, scale, skew)

常用格式

save();      //保存狀態
...          //具體操作
restore();   //回滾到之前的狀態
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章