
[Android]スクラッチのように画面をこすると下の画像が浮き出てくるサンプル#tryGraffitiScreen00

Viewを拡張してスクラッチを削るようにViewの色を落として下の画像をすかさせるような処理をする
線を引くというより、円を書いていって線を引く形にする。
setXfermodeをつかうと今書いてある背景を無視して塗りつぶす色が反映されるように設定することができる。
色が抜かれた場所を矩形で囲む
検索した事
android なぞった位置に線を引く
android プログラム らくがき
Android View 画面サイズが変更された
android Canvas setXfermode
開発環境
Eclipse IDE バージョン: 4.2.1
package com.example.trygraffitiscreen00; import android.os.Bundle; import android.app.Activity; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.view.Menu; public class TryGraffitiScreen00 extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_try_graffiti_screen00); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.activity_try_graffiti_screen00, menu); return true; } }
スライドした場所を画面に書き出すためのカスタムビュー
package com.example.trygraffitiscreen00; 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.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.RectF; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; // ______________________________________________________________________________ /** * 落書きビュー * */ public class GraffitiView extends View implements OnTouchListener { private Bitmap mWallBitmap; // 落書きされるビットマップ private Canvas mWallCanvas; // 落書きするためのキャンバス // ______________________________________________________________________________ /** * コンストラクタ * @param context コンテキスト */ public GraffitiView(Context context) { super(context); // タッチリスナーをセットする this.setOnTouchListener(this); } // ______________________________________________________________________________ /** * コンストラクタ * @param context * @param attrs * @param defStyle */ public GraffitiView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // タッチリスナーをセットする this.setOnTouchListener(this); } // ______________________________________________________________________________ /** * コンストラクタ * @param context * @param attrs */ public GraffitiView(Context context, AttributeSet attrs) { super(context, attrs); // タッチリスナーをセットする this.setOnTouchListener(this); } // ______________________________________________________________________________ /** * ビューサイズが変更された */ @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { // Bitmapを新しく作る this.mWallBitmap = null; this.mWallBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); // キャンバスを新しく作る this.mWallCanvas = null; this.mWallCanvas = new Canvas(this.mWallBitmap); // アルファで抜いていく画像を適当な透明度で初期化 this.mWallCanvas.drawColor(0xf9ffffff); super.onSizeChanged(w, h, oldw, oldh); } // ______________________________________________________________________________ /** * 描画通知 */ @Override protected void onDraw(Canvas canvas) { // 落書き用Bitmapに書かれた内容を表へ転送 canvas.drawBitmap(this.mWallBitmap, 0, 0, null); super.onDraw(canvas); } private Path mPath = new Path(); // ______________________________________________________________________________ /** * タッチされた時の処理 */ @Override public boolean onTouch(View v, MotionEvent event) { // タッチされた座標を取り出す float x = event.getX(); float y = event.getY(); Log.i("TOUCH:", "x: " + x + "y: " + y); // アクションを取り出し 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); // 線で繋がれた範囲のバウンディングボックスの計算 RectF bounds = new RectF(); this.mPath.computeBounds(bounds, true); // 線の太さ分外側に押し出す bounds.left -= 30; bounds.right += 30; bounds.top -= 30; bounds.bottom += 30; // バンディングボックスを描く this.drawBox(this.mWallCanvas, bounds); Log.i("BOUNDS", "l: " + bounds.left + " r: " + bounds.right + " t: " + bounds.top + " b: " + bounds.bottom); // 再描画通知 this.invalidate(); break; // タッチしたまま指が動かされた case MotionEvent.ACTION_MOVE: // パスをセットする this.mPath.lineTo(x, y); // ここまでの状態を書き込む this.drawPath(this.mWallCanvas, this.mPath); // 再描画通知 this.invalidate(); break; } return false; } // ______________________________________________________________________________ /** * BOXを描く * @param canvas キャンバス * @param r 矩形 */ private void drawBox(Canvas canvas, RectF r) { // 描画設定 Paint paint = new Paint(); paint.setDither(true); paint.setAntiAlias(true); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC)); paint.setColor(0xffff0000); // 線を描く paint.setStyle(Paint.Style.STROKE); // 矩形の指定に従って描き込む canvas.drawRect(r, paint); } // ______________________________________________________________________________ /** * パスに沿って線を書く * @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(60); canvas.drawPath(path, paint); } }
画面を構成するレイアウト
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".TryGraffitiScreen00" > <ImageView android:id="@+id/imageView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/bg" /> <com.example.trygraffitiscreen00.GraffitiView android:id="@+id/view1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:background="#00000000" /> </RelativeLayout>
[Android]値を変えたらそのまま保存、色選択プリファレンスアクティビティ... [Android]有料版 無料版をプロジェクトで分けるサンプル#tryFreeOrPay00
ありがとうございます
コメントありがとうございます。
何か参考にしていただければ幸いです。