コンピュータクワガタ

かっぱのかっぱによるコンピュータ関連のサイトです

Androidアプリ入門 No.76 2Dグラフィックスの基本 Canvasの基本

2Dグラフィックスの基本

Canvasの基本

最初に基本的な図形の描画を確認する。以下の条件でプロジェクトを作成する。

項目 内容
Project name Android2D
Build Target Android 1.6
Application name Android2D
Package name sample.a2
Create Activity Android2DActivity
Min SDK Version 4

まずは、Activityではなくグラフィック描画用のViewを用意する。

package sample.a2;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.view.View;

public class GraphicView extends View {
    public GraphicView(Context context) {
        super(context);
    }

    @Override
    public void onDraw(Canvas canvas) {
        // 座標系がわかるような罫線を引く
        Paint paint = new Paint();
        paint.setColor(Color.argb(75, 255, 255, 255));
        paint.setStrokeWidth(1);
        for (int y = 0; y < 800; y = y + 10) {
            canvas.drawLine(0, y, 479, y, paint);
        }
        for (int x = 0; x < 480; x = x + 10) {
            canvas.drawLine(x, 0, x, 799, paint);
        }

        // 線を書く
        paint.setColor(Color.RED);
        // だんだん大きくしていく。
        for (int i = 1; i <= 10; i++) {
            paint.setStrokeWidth(i);
            canvas.drawLine(i * 20 - 10, 10, i * 20 + 10, 10, paint);
        }

        paint.setColor(Color.rgb(0, 255, 0));
        paint.setStrokeWidth(10);
        canvas.drawLine(10, 40, 300, 70, paint);
        paint.setStrokeWidth(10);
        paint.setAntiAlias(true);
        canvas.drawLine(10, 60, 300, 90, paint);

        // 円を書く
        paint.setAntiAlias(false);
        paint.setColor(Color.BLUE);
        canvas.drawCircle(90, 150, 40, paint);
        paint.setColor(Color.RED);
        canvas.drawCircle(90, 150, 20, paint);
        // 中心店の確認用の線
        paint.setColor(Color.GREEN);
        paint.setStrokeWidth(1);
        // Y座標は150が中心
        canvas.drawLine(40, 150, 140, 150, paint);
        // X座標は90が中心
        canvas.drawLine(90, 100, 90, 200, paint);

        // 矩形を書く
        paint.setColor(Color.RED);
        paint.setStrokeWidth(1);
        canvas.drawRect(10, 200, 50, 240, paint);
        paint.setColor(Color.BLUE);
        paint.setStrokeWidth(5);
        canvas.drawRect(10, 250, 50, 290, paint);

        // 多角形を書く
        paint.setColor(Color.RED);
        Path path = new Path();
        path.moveTo(100, 300);
        path.lineTo(10, 350);
        path.lineTo(80, 330);
        canvas.drawPath(path, paint);

        // 文字を書く
        paint.setAntiAlias(false);
        paint.setColor(Color.rgb(255, 255, 0));
        paint.setTextSize(36);
        canvas.drawText("あいうえお", 10, 400, paint);
        paint.setAntiAlias(true);
        canvas.drawText("あいうえお", 10, 450, paint);

        // Pathに沿って文字を書く
        paint.setColor(Color.RED);
        path = new Path();
        path.moveTo(50, 500);
        path.lineTo(250, 500);
        path.lineTo(250, 600);
        path.lineTo(50, 600);
        canvas.drawTextOnPath("あいうえおかきくけこさしすせそ", path, 0, 0, paint);
        paint.setColor(Color.GREEN);
    }
}

次に、そのViewを表示するAndroid2DActivity.javaを以下のようにする。

package sample.a2;

import android.app.Activity;
import android.os.Bundle;

public class Android2DActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new GraphicView(this));
    }
}

実行結果は以下のようになる。

使用したAPIを簡単に確認する。まずPaintクラスから解説する。Paintクラスは描画のための色やスタイルの情報のクラスとなる。Paintクラス自体は色やスタイルの情報を持つだけで実際の描画は行わない。色情報を設定するPaint#setColorメソッドの定義は以下のようになっている。

public void setColor(int color)

引数の詳細は以下。

引数 説明
color 色情報をint型で指定する。通常はintの数値をリテラルで指定するのは可読性に欠けるため、Colorクラスを用いたりリソースを用いて指定する。

Colorクラスでの色の指定は以下のパターンで行う。

引数 説明
Color#rgb(int red, int green, int blue) red、green、blueを0〜255の比率で指定する。
Color#argb(int alpha, int red, int green, int blue) alpha、red、green、blueを0〜255の比率で指定する。
Color#定数 定数には、BLACK、BLUE、CYAN、DKGRAY、GRAY、GREEN、LTGRAY、MAGENTA、RED、TRANSPARENT、WHITE、YELLOW等がある。

線の幅は、Paint#setStrokeWidthメソッドで定義する。具体的な定義は以下。

public void setStrokeWidth(float width)
引数 説明
width 線の幅。

アンチエイリアスAPIのレベルで行うことができ、Paint#setAntiAliasで設定できる。具体的な定義は以下。

public void setAntiAlias(boolean aa)
引数 説明
aa アンチエイリアスをする場合にはtrue。

アンチエイリアスの効果を拡大して確認。

次にPaintを用いて実際に描画を行う。描画はCanvasクラスを用いて行う。代表的なメソッドをいくつか解説する。まず、単純な線を引くCanvas#drawLineメソッドを説明する。定義は以下。

public void drawLine(float startX, float startY, float stopX, float stopY,
Paint paint)
引数 説明
startX 線を引くx座標の開始。
startY 線を引くy座標の開始。
stopX 線を引くx座標の終了。
stopY 線を引くy座標の終了。
paint 線を引くPaintクラスのインスタンス

次に円を描画するCanvas#drawCircleメソッドを説明する。定義は以下。

public void drawCircle (float cx, float cy, float radius, Paint paint)
引数 説明
cx 円の中心のx座標。
cy 円の中心のy座標。
radius 円の半径。
paint 円を描くPaintクラスのインスタンス

次に矩形を描画するCanvas#drawRectメソッドを説明する。定義は以下。

public void drawRect (float left, float top, float right, float bottom,
Paint paint)
引数 説明
left 矩形の左端のx座標。
top 矩形の上端のy座標。
right 矩形の右端のx座標。
bottom 矩形の下端のy座標。
paint 円を描くPaintクラスのインスタンス

次に多角形の描画をするCanvas#drawPathメソッドを説明する。定義は以下。

public void drawPath(Path path, Paint paint)
引数 説明
path どのようなPathを描くか。
paint Pathを描くPaintクラスのインスタンス

ここで出てきたPathクラスは、任意の点を指定してそれらを結んだ形を塗りつぶして描画する。例のプログラムの以下の部分に当たる。
// 多角形を書く

paint.setColor(Color.RED);
Path path = new Path();
path.moveTo(100, 300);
path.lineTo(10, 350);
path.lineTo(80, 330);
canvas.drawPath(path, paint);

Pathクラスは、インスタンスを作成後、始点をPath#moveToメソッドで決める。その点から、任意の点をPath#lineToメソッドで結ぶ。drawPathの場合には点は閉じていなくても(最初の点に戻らなくても)自動的に閉じた形で矩形が描画される。

次に、Pathに沿って文字列を描画するPath#メソッドを説明する。定義は以下。

public void drawTextOnPath(String text, Path path, float hOffset, float vOffset,
Paint paint)
引数 説明
text 描画する文字列。
path どのようなPathを描くか。
hOffset 横方向のオフセット。
vOffset 縦方向のオフセット。
paint Pathを描くPaintクラスのインスタンス

図形の描画と違いpathは始点で閉じられることはない。Path#moveToからPath#lineToまでで描いたPathに沿って文字列が描画される。Pathよりも文字列のほうが長ければ文字列はそこで打ち切られる。

hOffsetとvOffsetの動きを確認するため以下のサンプルを実行する。GraphicViewのみ以下のように変更して実行する。GraphicView.javaは以下。

package sample.a2;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.view.View;

public class GraphicView extends View {
    public GraphicView(Context context) {
        super(context);
    }

    @Override
    public void onDraw(Canvas canvas) {
        // 座標系がわかるような罫線を引く
        Paint paint = new Paint();
        paint.setColor(Color.argb(75, 255, 255, 255));
        paint.setStrokeWidth(1);
        for (int y = 0; y < 800; y = y + 10) {
            canvas.drawLine(0, y, 479, y, paint);
        }
        for (int x = 0; x < 480; x = x + 10) {
            canvas.drawLine(x, 0, x, 799, paint);
        }

        // Pathに沿って文字を書く
        paint.setColor(Color.RED);
        paint.setTextSize(36);
        Path path = new Path();
        path.moveTo(100, 100);
        path.lineTo(400, 100);
        canvas.drawTextOnPath("あいうえお", path, 0, 0, paint);

        path = new Path();
        path.moveTo(100, 200);
        path.lineTo(400, 200);
        canvas.drawTextOnPath("あいうえお", path, 50, 0, paint);

        path = new Path();
        path.moveTo(100, 300);
        path.lineTo(400, 300);
        canvas.drawTextOnPath("あいうえお", path, 0, 50, paint);

        paint.setColor(Color.YELLOW);
        canvas.drawLine(100, 100, 400, 100, paint);
        canvas.drawLine(100, 200, 400, 200, paint);
        canvas.drawLine(100, 300, 400, 300, paint);
    }
}

実行結果は以下のようになる。黄色い線でPathを表している。PathとのずれでhOffset、vOffsetの効果がわかるようになっている。