画面を掃除するようなView:Android

More than 1 year has passed since last update.

今回、画面が徐々に汚くなる→指で掃除をする、みたいな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();
}

}