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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Q&A

解決済

1回答

2498閲覧

お絵描きアプリで消しゴムとペンを切り替えられるようにしたい

tery0203

総合スコア12

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

0グッド

0クリップ

投稿2019/03/04 11:56

前提・実現したいこと

現在、本体ストレージに保存されている画像を開きそれにお絵描きができるようなアプリを開発しています。
下部に「消しゴム」「黒ペン」「赤ペン」のボタンを配置し、それを押すと各機能に切り替えられるようにしたいのですが、消しゴムだけうまく機能せず実装できません。

発生している問題・エラーメッセージ

「消しゴム」ボタンを押すとペンの色が黒で描画され、それから「赤ペン」ボタンを押しても色が変わらない

該当のソースコード

DrawActivity

1 2public class DrawActivity extends AppCompatActivity implements View.OnClickListener { 3 4 String mDrawUri; 5 Uri mUri; 6 7 private PaintView paintView; 8 Button eraser,black_button,red_button; 9 10 protected void onCreate(Bundle savedInstanceState) { 11 12 // OnCreateで前画面から選択された画像のパスをインテントで渡し、 13 // imageviewに渡す処理をしていますがここでは割愛 14 15 // 以下がお絵描きに関わる部分のコードです 16 17 eraser= findViewById(R.id.eraser); 18 black_button= findViewById(R.id.black_button); 19 red_button= findViewById(R.id.red_button) ; 20 eraser.setOnClickListener(this); 21 black_button.setOnClickListener(this); 22 red_button.setOnClickListener(this); 23 24 // 表示したimageviewの上に描画用のviewをFrameLayoutで重ねて表示しています 25 this.paintView = findViewById(R.id.PaintView); 26 27 findViewById(R.id.delete_button).setOnClickListener(deleteDrawing); 28 29 } 30 31 View.OnClickListener deleteDrawing = new View.OnClickListener(){ 32 @Override 33 public void onClick(View view){ 34 paintView.delete(); 35 } 36 }; 37 38 39 public void onClick(View v){ 40 switch(v.getId()){ 41 case R.id.eraser: 42 paintView.setPen(Color.TRANSPARENT); 43 Toast.makeText(this,"消しゴムで消去できます",Toast.LENGTH_SHORT).show(); 44 break; 45 case R.id.black_button: 46 paintView.setPen(Color.BLACK); 47 Toast.makeText(this,"黒色で描画します",Toast.LENGTH_SHORT).show(); 48 break; 49 case R.id.red_button: 50 paintView.setPen(Color.RED); 51 Toast.makeText(this,"赤色で描画します", Toast.LENGTH_SHORT).show(); 52 break; 53 } 54 } 55 56 @Override 57 public void onPointerCaptureChanged(boolean hasCapture) { 58 59 } 60} 61

PaintView

1public class PaintView extends View { 2 // 履歴 3 private List<DrawLine> lines; 4 // 現在、描いている線の情報 5 private Paint paint; 6 private Path path; 7 8 // 線の履歴(座標+色) 9 class DrawLine { 10 private Paint paint; 11 private Path path; 12 13 DrawLine(Path path, Paint paint) { 14 this.paint = new Paint(paint); 15 this.path = new Path(path); 16 } 17 18 void draw(Canvas canvas) { 19 canvas.drawPath(this.path, this.paint); 20 } 21 } 22 23 public PaintView(Context context) { 24 super(context); 25 } 26 27 public PaintView(Context context, AttributeSet attrs) { 28 super(context, attrs); 29 30 this.path = new Path(); 31 32 this.paint = new Paint(); 33 this.paint.setStyle(Paint.Style.STROKE); 34 this.paint.setAntiAlias(true); 35 this.paint.setStrokeWidth(5); 36 // 配列の設定 37 // 線の色ごとの保存とかしてる(いずれUndoとか実装したい) 38 this.lines = new ArrayList<DrawLine>(); 39 } 40 41 @Override 42 protected void onDraw(Canvas canvas) { 43 super.onDraw(canvas); 44 45 // キャンバスをクリア 46 canvas.drawColor(Color.TRANSPARENT); 47 // 履歴から線を描画 48 for(DrawLine line : this.lines) { 49 line.draw(canvas); 50 } 51 // 現在、描いている線を描画 52 canvas.drawPath(this.path, this.paint); 53 } 54 55 @Override 56 public boolean onTouchEvent(MotionEvent event) { 57 float x = event.getX(); 58 float y = event.getY(); 59 60 switch (event.getAction()) { 61 case MotionEvent.ACTION_DOWN: 62 this.path.moveTo(x, y); 63 break; 64 case MotionEvent.ACTION_MOVE: 65 this.path.lineTo(x, y); 66 break; 67 case MotionEvent.ACTION_UP: 68 this.path.lineTo(x, y); 69 // 指を離したので、履歴に追加する 70 this.lines.add(new DrawLine(this.path, this.paint)); 71 // パスをリセットする 72 // これを忘れると、全ての線の色が変わってしまう 73 this.path.reset(); 74 break; 75 } 76 invalidate(); 77 return true; 78 } 79 80 public void delete() { 81 // 履歴をクリア 82 this.lines.clear(); 83 // 現在の線をクリア 84 this.path.reset(); 85 invalidate(); 86 } 87 88 // 色の設定 89 // ここが原因で色が変わらなくなっている? 90 public void setPen(int color){ 91 if (color == 0) { 92 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); 93 }else {} 94 this.paint.setColor(color); 95 } 96 97

試したこと

「消しゴム」ボタンが押されたことを判定するためにif式などを使ってみるも改善しなかった

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

setPen で, color が 0 に設定されたときに実行されております setXfermode を, color が 0 以外に(再)設定されたときに戻さなければいけないのではないでしょうか.

投稿2019/03/04 18:25

jimbe

総合スコア12632

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tery0203

2019/03/05 15:42 編集

回答ありがとうございます。 elseの中に paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER)); を追加することで黒ペン、赤ペンを押した時はいつでも該当の機能が使えるようになりました。 ですが、消しゴムを押した時に黒の軌跡になってしまう現象は改善しませんでした… PorterDuff.Mode.CLEARだとおそらく下の画像ごと消えてしまっており、背景の黒が表示されてしまっているのではないかと予測できるのですが、他のモードに変えても消しゴムになるものはありませんでした。
jimbe

2019/03/05 18:22

color == 0 時に設定している CLEAR を SRC_OUT にしても変わらなかったでしょうか. また, 調べていると「ハードウェアアクセラレータが有効の場合に CLEAR の動作が定義と異なる場合がある」という記事が見受けられました. PaintView のコンストラクタで ```setLayerType(View.LAYER_TYPE_SOFTWARE, null);``` とするとハードウェアアクセラレータが無効になるそうなので, お試し頂けますでしょうか.
tery0203

2019/03/07 14:10 編集

コンストラクタにsetLayerType(View.LAYER_TYPE_SOFTWARE, null);を入れ、モードをCLEARにすることで消しゴムのように線が消えました! ハードウェアアクセラレータ周りはまだ勉強不足でしたので、これを機に色々調べてみようと思います。 ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問