質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.37%

android で消しゴム機能を作成したい

受付中

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,918

score 13

androidstudio(バージョン3.0.1)で、図形に線などを書き込めるものを作成しています。
しかし、今現在消しゴムは背景と同色で描く様にしているので、図形に記述した線を消してしまうと、図形の線まで消えてしまいます。

そこで、タッチイベントが終わった後に再びonDrawメソッドを呼び出し、
図形部分を再描画したらどうかと思ったのですが、調べてもやり方が分かりませんでした。

消しゴム機能等に関して、アドバイス等なんでもいいので、教えて頂けると嬉しいです。
宜しくお願いします。

public class Oekaki3 extends AppCompatActivity {
    private Paint paint1;
    private Path path1;

    private List<DrawInfo> draw_List = new ArrayList<>();
    private float pos_x, pos_y;
    int ket = 0;

    //ペンをセット
    protected void setPen(int selColor, float penWidth) {
        paint1 = new Paint();
        paint1.setAntiAlias(true);
        paint1.setColor(selColor);
        paint1.setStyle(Paint.Style.STROKE);
        paint1.setStrokeWidth(penWidth);
        paint1.setStrokeCap(Paint.Cap.ROUND);
        paint1.setStrokeJoin(Paint.Join.ROUND);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_oekaki3);
        TextView textView = new TextView(this);
        setContentView(textView);
        setPen(rgb(0, 0, 0), 15);
    }

    class TextView extends View {
        private Paint paint2;
        private Path path2;
        public TextView(Context context) {
            super(context);
            this.path2 = new Path();
            this.paint2 = new Paint();
        }

        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            canvas.drawPath(path2, paint2);
            canvas.drawColor(Color.rgb(255, 255, 255));
            Path path = new Path();
            paint2.setStyle(Paint.Style.STROKE);
            paint2.setStrokeWidth(7);

            paint2.setTextSize(50);
            canvas.drawText("下の図でAD=AB, DC=BCのとき", 300, 115, paint2);
            canvas.drawText("∠B=∠Dとなることを証明しなさい。", 300, 215, paint2);
            paint2.setTextSize(50);
            canvas.drawText("A", 350, 600, paint2);
            canvas.drawText("B", 600, 330, paint2);
            canvas.drawText("C", 1280, 600, paint2);
            canvas.drawText("D", 600, 900, paint2);

            //四角形の描写
            paint2.setStrokeWidth(10);
            // (x1,y1,x2,y2,paint) 始点の座標(x1,y1), 終点の座標(x2,y2)
            canvas.drawLine(400, 600, 600, 850, paint2);//AB間の線
            canvas.drawLine(600, 850, 1250, 600, paint2);//BC間の線
            canvas.drawLine(1250, 600, 600, 350, paint2);//CD間の線
            canvas.drawLine(600, 350, 400, 600, paint2);//DA間の線
            canvas.drawPath(path, paint2);

            Bitmap bac = BitmapFactory.decodeResource(getResources(), back);
            canvas.drawBitmap(bac, 30, 30, paint2);
            Bitmap res = BitmapFactory.decodeResource(getResources(), reset);
            canvas.drawBitmap(res, 2350, 30, paint2);
            Bitmap ke = BitmapFactory.decodeResource(getResources(), kesigomu);
            canvas.drawBitmap(ke, 2370, 280, paint2);
            Bitmap ku = BitmapFactory.decodeResource(getResources(), kuro);
            canvas.drawBitmap(ku, 2350, 450, paint2);
            Bitmap kk = BitmapFactory.decodeResource(getResources(), ye);
            canvas.drawBitmap(kk, 2350, 600, paint2);
            Bitmap pp = BitmapFactory.decodeResource(getResources(), pi);
            canvas.drawBitmap(pp, 2350, 750, paint2);
            Bitmap miz = BitmapFactory.decodeResource(getResources(), mizu);
            canvas.drawBitmap(miz, 2350, 900, paint2);
            Bitmap kim = BitmapFactory.decodeResource(getResources(), kimi);
            canvas.drawBitmap(kim, 2350, 1050, paint2);

            for (int i = 0; i < draw_List.size(); i++) {
                DrawInfo info = draw_List.get(i);
                canvas.drawPath(info.path, info.paint);//pathに保存したものを描く
            }
            if (path1 != null) {
                canvas.drawPath(path1, paint1);//最後に保存したものを描く
            }
        }

        @Override
        public boolean onTouchEvent(MotionEvent event) {
            pos_x = event.getX();//タッチしたX、Y座標を得る
            pos_y = event.getY();

            Log.d("TouchEvent", "X:" + event.getX() + ",Y:" + event.getY());//取得した内容をログに表示

            if (pos_x > 2350 && pos_x < 2590 && pos_y > 50 && pos_y < 240) {//はじめから
                path1.reset();
                draw_List.clear();
            } else if (pos_x > 2350 && pos_x < 2590 && pos_y > 240 && pos_y < 450) {//消しゴム
                draw_List.add(new DrawInfo(path1, paint1));
                setPen(rgb(255, 255, 255), 20);
            } else if (pos_x > 2350 && pos_x < 2590 && pos_y > 450 && pos_y < 600) {
                draw_List.add(new DrawInfo(path1, paint1));
                setPen(rgb(50, 50, 50), 20);//黒
            } else if (pos_x > 2350 && pos_x < 2590 && pos_y > 600 && pos_y < 750) {
                draw_List.add(new DrawInfo(path1, paint1));
                setPen(rgb(255, 200, 80),20);//黄色
            } else if (pos_x > 2350 && pos_x < 2590 && pos_y > 750 && pos_y < 900) {
                draw_List.add(new DrawInfo(path1, paint1));
                setPen(rgb(255, 203, 255), 20); //ピンク
            } else if (pos_x > 2350 && pos_x < 2590 && pos_y > 900 && pos_y < 1050) {
                draw_List.add(new DrawInfo(path1, paint1));
                setPen(rgb(161, 230, 255), 20); //水色
            } else if (pos_x > 2350 && pos_x < 2590 && pos_y > 1050 && pos_y < 1200) {
                draw_List.add(new DrawInfo(path1, paint1));
                setPen(rgb(207, 255, 139), 20); //黄緑
            } else if (pos_x > 30 && pos_x < 320 && pos_y > 30 && pos_y < 280) {//戻る
                finish();

            } else {

                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        path1 = new Path();
                        path1.moveTo(pos_x, pos_y);
                        break;

                    case MotionEvent.ACTION_MOVE:
                        path1.lineTo(pos_x, pos_y);
                        break;

                    case MotionEvent.ACTION_UP:
                        path1.lineTo(event.getX(), event.getY());
                        draw_List.add(new DrawInfo(path1, paint1));
                        path1.reset();
                        break;
                }
            }
            invalidate();
            return true;//タッチイベントの消費
        }
    }
}


イメージ説明
ピンクの線が記述した線、四角形ABCDが消したくない図形です。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

0

元にしたい図形に関しては読み込み時に図形を描画して、ImageViewに設定してやればcanvas上で扱う必要がなくなり残り続けるのではないでしょうか?
イメージとしてはImageViewの上に重ねてCanvasでお絵描きできるようなかんじ。
(コードも書いてなくて試してすらいないので的外れてたらすみません。ダメそうだったらコメントください、もうちょっと調べます。)

回答追記:
背景を同色としていると言う部分を見逃していました汗
Canvasを透明色で塗りつぶすと言うのがあったのでそれであればCanvasのみが透明になって元画像は残るようにできるかもしれません。
Canvasを透明色で塗りつぶす
Canvasを部分的に任意の色で塗りつぶす(消しゴムみたいの)
Androidビュー 透過色で塗りつぶす

できないようでしたらまたコメントください。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/18 21:10

    返事を下さっていたのにもかかわらず、返事が遅れてしまいすみません。
    分かりやすい回答ありがとうございます。
    Imageviewで画像として図形を描画し実行してみましたが、結局消しゴムを使用するとCanvas上で白く塗ってしまうため、ImageViewにしても、図形は消えてしまいました。
    setPenで透明色が指定出来たらいいのですが..。
    または、SurfaceViewにしたら上手くいくのでしょうか?

    キャンセル

  • 2018/11/19 12:04

    同色にしていたら下も塗りつぶされてしまいますね、質問内容をきちんとみてませんでしたすみません。
    透明色を指定できそうな方法がありそうでしたので回答追記させていただきました。
    ダメそうでしたらまたコメントください。

    キャンセル

  • 2018/11/24 23:20 編集

    再びご回答、ありがとうございます。
    私はSurfaceViewではなく、Viewを使用しているので、3つ目のサイトを参考に、PorterDuff等を
    使用し試行錯誤してみたのですが、描いた軌跡は透明ではなく黒くなってしましました..。
    androidstudioは、背景が黒く設定されている(?)ということで、背景を透明にするなど試してみましたが、やはり黒い軌跡になってしまいます。

    CanvasやViewなどを2つ利用し、層を上下に設定することで、上の層には図形を、下の層にはタッチの軌跡を描画をしたら上手くいくのでは?と思ったのですが、その様なことは可能でしょうか?
    言葉で上手く表現できず、分かりにくかったらすみません。

    キャンセル

  • 2019/02/04 11:57

    いわゆる「レイヤー」のことでしょうか.

    キャンセル

0

TextureViewクラスでの実装の話ですが、参考にしてみて下さい。

Viewの背景をsetOpaque(false)にて透明にします(普通のViewなら"setAlpha")。
Canvasは、drawColor(Color.TRANSPARENT,PorteDuff.Mode.CLEAR)で背景を透明にします。
消しゴムのPaintの設定で、setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR))で透明で塗り潰せました。
setColor()は、#00000000でないとダメかもしれません。

以上、上記は携帯から手打ちなので綴りのミスがあるかもしれませんが、トライしてみて下さい。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.37%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る