[Android Tips] Viewでお絵かきしてみる

2011.09.02

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは!

今回から「Android Tips」と称しまして、Android開発の小ネタを少しずつ公開していきます。
簡単なものからふと発見した小ネタなど、幅広く紹介できればと思います。

テーマ「Viewでお絵かき」

さて、今回は「Viewを使ったお絵かき」についてご紹介します。

Viewとは?

そもそも、Viewとは何か簡単にご説明したいと思います。
Viewとは、その名の通り「見えている」ものです。つまりUIコンポーネントです。
ボタンや画像など、画面上に表示されるものはすべてViewを継承したクラスです。
今回はこのViewを使ってお絵かきしていきます。

お絵かきできるViewを作る

それでは、お絵かきできるViewを作っていきましょう。
今回のサンプルでは、Viewのタッチイベントを取得し、タッチされた場所に線を描いていきます。

1.Viewを継承したクラスを作成する

まずはViewを継承したクラスを作成します。サンプルではDrawViewという名前のクラスを作成しました。
クラスを作成しますと「明示的コンストラクターを定義する必要があります」というエラーが出ますので、
コンストラクタを作成します。引数はContextのみでOKです。

DrawView.java

package jp.cm.sample.draw;

import android.content.Context;
import android.view.View;

public class DrawView extends View{

	public DrawView(Context context) {
		super(context);
	}

}

これでひとまずViewができました。しかしこのままでは画面上に表示されませんので、
ActivityのsetContentView()メソッドでこのViewを表示させます。

DrawActivity.java

package jp.cm.sample.draw;

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

public class DrawActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        DrawView view = new DrawView(this);
        setContentView(view);
    }

}

2.onTouch()メソッドを実装する

次に、Viewがタッチされたときのイベントを取得します。
コンストラクタ内でsetOnTouchListener()メソッドを使い、イベントを取得できるようにします。
今回は引数にthisを指定し、View内でイベントを処理するonTouchメソッドをオーバーライドします。
※オーバーライドするには、Eclipseのメニューから「ソース」→「メソッドのオーバーライド/実装(V)...」を使うと楽です。

onTouch()メソッドにはMotionEventという引数が渡されます。
このMotionEventのgetAction()メソッドで「タッチイベントの種類」が取得できます。
今回は、タッチされたとき、タッチしたまま動かしたとき、タッチが解除されたときのイベントを使います。

	@Override
	public boolean onTouch(View v, MotionEvent event) {

		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			// タッチしたとき
			break;
		case MotionEvent.ACTION_MOVE:
			// タッチしたまま動かしたとき
			break;
		case MotionEvent.ACTION_UP:
			// 指を離したとき
			break;
		default:
		}
		return true;
	}

3.Pathクラスを使ってパスを描く

ここまでで絵を描くための準備が終わりました。
次に、実際に描く線のデータを作っていきたいと思います。
今回はonTouch()メソッドで取得できる情報を使ってパスを描きたいと思います。
パスを描くにはPathクラスを使います。
PathクラスにはmoveTo()メソッド、lineTo()メソッドがあります。
moveTo()メソッドでパスの開始地点を決め、lineTo()メソッドで描画するポイントを追加していきます。
今回は、タッチされるたびにPathオブジェクトを生成し、それをArrayListで記録しています。

4.onDraw()メソッドを実装する

最後に、onDraw()メソッドをオーバーライドします。
onDraw()メソッドは、Viewに描画するために用意されているメソッドです。
Canvasオブジェクトが引数で渡されますので、CanvasのdrawPath()メソッドを使ってパスを描画します。
また、実際に描く線の色などはPaintクラスを使って設定します。線を描く場合はsetStyle(Paint.Style.STROKE)が必須です。

また、今回の場合は明示的にonDraw()メソッドを実行させる必要があります。
Viewのinvalidate()メソッドを実行するとonDraw()メソッドが実行されますので、
onTouch()メソッド内に書きましょう。

ソース

package jp.cm.sample.draw;

import java.util.ArrayList;

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

public class DrawView extends View implements OnTouchListener{

	private Paint paint;

	private ArrayList<Path> pathList = new ArrayList<Path>();
	private Path path;

	public DrawView(Context context) {
		super(context);
		setOnTouchListener(this);

		paint = new Paint();
		paint.setColor(Color.GREEN);
		paint.setStyle(Paint.Style.STROKE);
		paint.setAntiAlias(true);
		paint.setStrokeWidth(10);
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		for (Path path : pathList) {
			canvas.drawPath(path, paint);
		}
	}

	@Override
	public boolean onTouch(View v, MotionEvent event) {

		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			// タッチしたとき
			path = new Path();
			path.moveTo(event.getX(), event.getY());
			pathList.add(path);
			break;
		case MotionEvent.ACTION_MOVE:
			// タッチしたまま動かしたとき
			path.lineTo(event.getX(), event.getY());
			break;
		case MotionEvent.ACTION_UP:
			// 指を離したとき
			path.lineTo(event.getX(), event.getY());
			break;
		default:
		}
		invalidate();
		return true;
	}

}

実行結果

(タブレットを使い、指でdroidさんを描いてみました。難しいですね…)

まとめ

今回は主にonTouch()メソッド、onDraw()メソッドを使ってお絵かきしてみました。
個人的にはASと似ているところもあり、わかりやすかったです。
ぜひお試しいただき、簡易メモなどに使ってみてください(笑)