今回、画面が徐々に汚くなる→指で掃除をする、みたいなViewを作成したので、備忘録的に投稿します。
ちょろちょろっと作成したものなので雑な作りです。
#プログラム
import java.util.Random;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuffXfermode;
import android.graphics.PorterDuff;
import android.os.Handler;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
public class DustView extends View implements OnTouchListener {
private Bitmap mWallBitmap; // 透明なビットマップ
private Canvas mWallCanvas; // キャンバス
private Path mPath = new Path();
private int dustLen = 0;
private long dustAddTime = 0;
private int displayWidth;
private int displayHeight;
private Paint dustPaint;
private Handler dustHandler;
/**
* コンストラクタ
* @param context コンテキスト
*/
public DustView(Context context, int dustLen, long dustAddTime) {
super(context);
// 煤の描画数と描画時間をセットする
this.dustLen= dustLen;
this.dustAddTime= dustAddTime;
// タッチリスナーをセットする
this.setOnTouchListener(this);
}
/**
* ビューサイズが変更された
*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
dustHandler = new Handler();
// ディスプレイサイズの取得
displayWidth = w;
displayHeight = h;
// 煤のペイントを作る
dustPaint = new Paint();
dustPaint.setColor(0x88000000);
// Bitmapを新しく作る
this.mWallBitmap = null;
this.mWallBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
// キャンバスを新しく作る
this.mWallCanvas = null;
this.mWallCanvas = new Canvas(this.mWallBitmap);
// 描画を開始する
autoRun();
super.onSizeChanged(w, h, oldw, oldh);
}
/**
* 描画通知
*/
@Override
protected void onDraw(Canvas canvas) {
// 落書き用Bitmapに書かれた内容を表へ転送
canvas.drawBitmap(this.mWallBitmap, 0, 0, null);
super.onDraw(canvas);
}
/**
* タッチされた時の処理
*/
@Override
public boolean onTouch(View v, MotionEvent event) {
// タッチされた座標を取り出す
float x = event.getX();
float y = event.getY();
// アクションを取り出し
int action = event.getAction();
switch (action) {
// タッチ開始
case MotionEvent.ACTION_DOWN:
// パスをリセットしてから新しい座標をセット
this.mPath.reset();
this.mPath.moveTo(x, y);
// ここまでの状態でパスに沿って線を書く。
// 最初だから○が描かれるだけ
this.drawPath(this.mWallCanvas, this.mPath);
// 再描画通知
this.invalidate();
return true; // ←trueを返さないとACTION_UPがやってこない
// タッチ終了
case MotionEvent.ACTION_UP:
// ここまでのパスをセット
this.mPath.lineTo(x, y);
// パスに沿って線を描く
this.drawPath(this.mWallCanvas, this.mPath);
// 再描画通知
this.invalidate();
break;
// タッチしたまま指が動かされた
case MotionEvent.ACTION_MOVE:
// パスをセットする
this.mPath.lineTo(x, y);
// ここまでの状態を書き込む
this.drawPath(this.mWallCanvas, this.mPath);
// 再描画通知
this.invalidate();
break;
}
return false;
}
/**
* パスに沿って線を書く
* @param canvas キャンバス
* @param path パス
*/
private void drawPath(Canvas canvas, Path path) {
// 線を書くためのペイント
Paint paint = new Paint();
paint.setDither(true);
paint.setAntiAlias(true);
// これをすると塗りつぶす方の色が優先される
// 背景のアルファを無視して下のレイアウトが見えるようになる
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
paint.setColor(Color.argb(0, 0x00, 0, 0));
// 線を引く設定(角をどうするかとか)
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStrokeJoin(Paint.Join.ROUND);
// 太めに
paint.setStrokeWidth(120);
canvas.drawPath(path, paint);
}
private void autoRun(){
dustHandler.postDelayed(new Runnable() {
@Override
public void run() {
addDust();
autoRun();
}
}, dustAddTime);
}
private void addDust(){
//Randomクラスのインスタンス化
for(int i = 0; i < dustLen; i++)
{
Random rnd = new Random();
int widthRan = rnd.nextInt(displayWidth);
int heightRan = rnd.nextInt(displayHeight);
this.mWallCanvas.drawCircle(widthRan, heightRan, 2, dustPaint);
}
this.invalidate();
}
}