Canvasに図形を描画する|Android開発

androidでCanvasへ図形や文字を描画する方法です。
SurfaceViewを継承したビューを作成し、onDraw()がコールされた時などにCanvasへ描画を行います。

描画用クラスのサンプル

public class PaintView extends SurfaceView implements SurfaceHolder.Callback {
    private static final String TAG = "PaintView";

    private int mCurrentWidth = 0;
    private int mCurrentHeight = 0;

    private SurfaceHolder mHolder;

    public PaintView(Context context) {
        this(context, null);
    }

    public PaintView(Context context, AttributeSet attrs) {
        super(context, attrs);

        mHolder = getHolder();
        mHolder.addCallback(this);
        setWillNotDraw(false);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        Log.i(TAG, "surfaceCreated");
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        Log.i(TAG, "surfaceChanged");
        if (mCurrentWidth == width && mCurrentHeight == height) {
            return;
        }

        mCurrentWidth = width;
        mCurrentHeight = height;
        doDraw();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        Log.i(TAG, "surfaceDestroyed");
    }

    private void doDraw() {
        Canvas canvas = mHolder.lockCanvas();
        if (canvas == null) {
            Log.e(TAG, "SurfaceHolder.lockCanvas() is null.");
            return;
        }

        doDraw(canvas);

        mHolder.unlockCanvasAndPost(canvas);
    }

    /**
     * 実際の描画処理.
     */
    private void doDraw(Canvas canvas) {
        if (mCurrentWidth == 0 || mCurrentHeight == 0) {
            return;
        }
        Paint paint = new Paint();

        // 背景を塗り潰す.
        canvas.drawColor(Color.WHITE);

        // 描画処理.
    }

    @Override
    public void onDraw(Canvas canvas) {
        Log.i(TAG, "onDraw");
        doDraw(canvas);
    }
}
setWillNotDraw()
trueを設定するとonDraw()が呼ばれなくなります。

Canvas の描画メソッド

Canvasクラスの描画メソッドとサンプルです。上記サンプルのdoDraw()の中で使用します。

背景を塗り潰す

canvas.drawColor(Color.BLUE);
canvas.drawColor

線を引く

引数はstartX, startY, stopX, stopYの順で(startX, startY)から(stopX, stopY)に線を引きます。

canvas.drawLine(0.f, 0.f, mCurrentWidth, mCurrentHeight, paint);
canvas.drawLine

複数の線を引く

第1引数は座標の配列。個数は4の倍数でx1, y2, x2, y2の順で(x1, y1)から(x2, y2)に線を引きます。以降、このセットの繰り返し。
配列の要素数を4個にして1本だけ線を引くことも可能です。

canvas.drawLines(new float[]{
        0.f, 0.f, mCurrentWidth / 2.f, mCurrentHeight,                 // 1本目の線の座標.
        mCurrentWidth / 2.f, mCurrentHeight, mCurrentWidth / 2.f, 0.f, // 2本目の線の座標.
}, paint);
canvas.drawLines

円を描画する

引数は円の中心座標x, y, 半径の長さの順。

canvas.drawCircle(mCurrentWidth / 2.f, mCurrentHeight / 2.f, mCurrentHeight / 2.f, paint);
canvas.drawCircle

楕円を描画する

指定した矩形に隣接する楕円を描画します。

canvas.drawOval(new RectF(0.f, 0.f, mCurrentWidth / 2.f, mCurrentHeight), paint);
canvas.drawOval

四角形を描画する.

canvas.drawRect(new RectF(0.f, 0.f, mCurrentWidth / 2.f, mCurrentHeight), paint);
canvas.drawRect

Paint の設定

描画幅を変更する

paint.setStrokeWidth(5);
paint.setStrokeWidth

描画色を変更する

paint.setColor(Color.RED);

ARGBで指定する場合。

paint.setColor(0xFFFF0000);
paint.setColor

円や矩形を塗り潰さないようにする

setStyle()Paint.Style.STROKEを指定すると、円や矩形の描画で枠線のみを描画します。

paint.setStyle(Paint.Style.STROKE);
Paint.Style.STROKE

文字列描画の文字サイズ

paint.setTextSize(20);

文字列の描画

文字列描画の座標は左、下(ベースライン)を指定します。

measureText()で文字列描画時の幅を取得できます。

// 文字列描画用の Paint インスタンス.
Paint labelPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
labelPaint.setTextSize(20);
labelPaint.setColor(Color.BLACK);

float labelWidth = labelPaint.measureText("blue days.");
canvas.drawText("blue days.", mCurrentWidth - labelWidth, 50, labelPaint);
canvas.drawText

getTextBounds()で文字列描画時の矩形を取得できます。

// 文字列描画用の Paint インスタンス.
Paint labelPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
labelPaint.setTextSize(20);
labelPaint.setColor(Color.BLACK);

Rect rect = new Rect();
labelPaint.getTextBounds("BLUE DAYS.", 0, "BLUE DAYS.".length(), rect);
canvas.drawText("BLUE DAYS.", mCurrentWidth - rect.width(), rect.height(), labelPaint);

paint.setColor(Color.RED);
canvas.drawLine(mCurrentWidth - rect.width(), rect.height(), mCurrentWidth, rect.height(), paint);
canvas.drawText ベースライン

文字列を回転して描画する

文字列を縦方向に描画したい場合など。

  1. Canvas.save()で現在のキャンバス描画情報を保存する
  2. Canvas.rotate()でキャンバスを回転させる
    Canvas.save()~Canvas.restore()までの描画が回転する
  3. 描画処理を行う(座標は回転前の値)
  4. Canvas.restore()で保存した描画情報を戻す
描画処理の座標はrotate()で指定した座標を中心に回転することを考えて逆算する。
// 文字列描画用の Paint インスタンス.
Paint labelPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
labelPaint.setTextSize(20);
labelPaint.setColor(Color.BLACK);

// ビューの中心座標で回転させる.
float cx = getWidth() / 2.f;
float cy = getHeight() / 2.f;

paint.setColor(Color.RED);
canvas.drawLines(new float[] {
        0.f, cy, mCurrentWidth, cy,
        cx, 0.f, cx, mCurrentHeight,
}, paint);

canvas.save();
Rect rect = new Rect();
labelPaint.getTextBounds("rotate 90.", 0, "rotate 90.".length(), rect);
canvas.rotate(90, cx, cy);

paint.setColor(Color.CYAN);
canvas.drawRect(new RectF(cx - rect.width(), cy - rect.height(), cx, cy), paint);

canvas.drawText("rotate 90.", cx - rect.width(), cy, labelPaint);
canvas.restore();
canvas.rotate canvas.rotate
このエントリーをはてなブックマークに追加
にほんブログ村 IT技術ブログへ

コメント

メールアドレスが公開されることはありません。 が付いている欄は必須項目です