2016-12-12 2 views
4

Целью является возможность писать/эскиз/рисовать что-либо поверх полученного изображения, а также стирать, не разрушая изображение, при этом изображение остается неповрежденным, а при сохранении изображения рисунок и изображение на заднем плане будут включены в окончательный вывод.Android: Как реализовать рисунок поверх изображения

Я создал приложение, которое берет фотографию, и отправляет ее в новое действие для предварительного просмотра и редактирования, где я должен рисовать изображение, как круг или некоторые строки. Я смог сделать это, создав растровое изображение и передав его через новый конструктор Canvas().

Проблема с этим я могу написать на изображении, но когда я использую режим стирания, изображение также стирается, я хотел бы реализовать что-то, что позволило бы мне стереть, не разрушая фоновое изображение, и в то же время время, когда изображение на фоне все равно будет включено, когда я сохраню изображение, наконец.

Код для моего вида ниже.

import android.content.Context; 
import android.content.res.Resources; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.graphics.BitmapShader; 
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.Shader; 
import android.util.AttributeSet; 
import android.util.TypedValue; 
import android.view.MotionEvent; 
import android.view.View; 

public class DrawingView extends View { 

    //drawing path 
    private Path drawPath; 
    //drawing and canvas paint 
    private Paint drawPaint, canvasPaint; 
    //initial color 
    private int paintColor = 0xFF660000, paintAlpha = 255; 
    //canvas 
    private Canvas drawCanvas; 
    //canvas bitmap 
    private Bitmap canvasBitmap; 
    //brush sizes 
    private float brushSize, lastBrushSize; 
    //erase flag 
    private boolean erase=false; 

    Bitmap bg; 

    public DrawingView(Context context, AttributeSet attrs){ 
     super(context, attrs); 
     setupDrawing(); 
    } 

    //setup drawing 
    private void setupDrawing(){ 

     //prepare for drawing and setup paint stroke properties 
     brushSize = getResources().getInteger(R.integer.medium_size); 
     lastBrushSize = brushSize; 
     drawPath = new Path(); 
     drawPaint = new Paint(); 
     drawPaint.setColor(paintColor); 
     drawPaint.setAntiAlias(true); 
     drawPaint.setStrokeWidth(brushSize); 
     drawPaint.setStyle(Paint.Style.STROKE); 
     drawPaint.setStrokeJoin(Paint.Join.ROUND); 
     drawPaint.setStrokeCap(Paint.Cap.ROUND); 
     canvasPaint = new Paint(Paint.DITHER_FLAG); 

     Resources res = getResources(); 
     Bitmap bitmap = BitmapFactory.decodeResource(res, R.drawable.background); 
     bg = bitmap.copy(Bitmap.Config.ARGB_8888, true); 
    } 

    //size assigned to view 
    @Override 
    protected void onSizeChanged(int w, int h, int oldw, int oldh) { 
     super.onSizeChanged(w, h, oldw, oldh); 
     canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); 
     drawCanvas = new Canvas(bg); 
    } 

    //draw the view - will be called after touch event 
    @Override 
    protected void onDraw(Canvas canvas) { 
     canvas.drawBitmap(bg, 0, 0, canvasPaint); 
     canvas.drawPath(drawPath, drawPaint); 
    } 

    //register user touches as drawing action 
    @Override 
    public boolean onTouchEvent(MotionEvent event) { 
     float touchX = event.getX(); 
     float touchY = event.getY(); 
     //respond to down, move and up events 
     switch (event.getAction()) { 
      case MotionEvent.ACTION_DOWN: 
       drawPath.moveTo(touchX, touchY); 
       break; 
      case MotionEvent.ACTION_MOVE: 
       drawPath.lineTo(touchX, touchY); 
       break; 
      case MotionEvent.ACTION_UP: 
       drawPath.lineTo(touchX, touchY); 
       drawCanvas.drawPath(drawPath, drawPaint); 
       drawPath.reset(); 
       break; 
      default: 
       return false; 
     } 
     //redraw 
     invalidate(); 
     return true; 

    } 

    //update color 
    public void setColor(String newColor){ 
     invalidate(); 
     //check whether color value or pattern name 
     if(newColor.startsWith("#")){ 
      paintColor = Color.parseColor(newColor); 
      drawPaint.setColor(paintColor); 
      drawPaint.setShader(null); 
     } 
     else{ 
      //pattern 
      int patternID = getResources().getIdentifier(
        newColor, "drawable", "com.example.drawingfun"); 
      //decode 
      Bitmap patternBMP = BitmapFactory.decodeResource(getResources(), patternID); 
      //create shader 
      BitmapShader patternBMPshader = new BitmapShader(patternBMP, 
        Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); 
      //color and shader 
      drawPaint.setColor(0xFFFFFFFF); 
      drawPaint.setShader(patternBMPshader); 
     } 
    } 

    //set brush size 
    public void setBrushSize(float newSize){ 
     float pixelAmount = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 
       newSize, getResources().getDisplayMetrics()); 
     brushSize=pixelAmount; 
     drawPaint.setStrokeWidth(brushSize); 
    } 

    //get and set last brush size 
    public void setLastBrushSize(float lastSize){ 
     lastBrushSize=lastSize; 
    } 
    public float getLastBrushSize(){ 
     return lastBrushSize; 
    } 

    //set erase true or false 
    public void setErase(boolean isErase){ 
     erase=isErase; 
     drawPaint.setColor(Color.parseColor("#FFFFFF")); 
     if(erase) drawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); 
     else drawPaint.setXfermode(null); 
     drawPaint.setColor(paintColor); 
    } 

    //start new drawing 
    public void startNew(){ 
     drawCanvas.drawColor(0, PorterDuff.Mode.CLEAR); 
     invalidate(); 
    } 

    //return current alpha 
    public int getPaintAlpha(){ 
     return Math.round((float)paintAlpha/255*100); 
    } 

    //set alpha 
    public void setPaintAlpha(int newAlpha){ 
     paintAlpha=Math.round((float)newAlpha/100*255); 
     drawPaint.setColor(paintColor); 
     drawPaint.setAlpha(paintAlpha); 
    } 
} 

MainActivity.java это

import android.app.Activity; 
import android.app.AlertDialog; 
import android.app.Dialog; 
import android.content.DialogInterface; 
import android.os.Bundle; 
import android.provider.MediaStore; 
import android.view.Menu; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.Button; 
import android.widget.ImageButton; 
import android.widget.LinearLayout; 
import android.widget.SeekBar; 
import android.widget.SeekBar.OnSeekBarChangeListener; 
import android.widget.TextView; 
import android.widget.Toast; 

import java.util.UUID; 


public class MainActivity extends Activity implements OnClickListener { 

    //custom drawing view 
    private DrawingView drawView; 
    //buttons 
    private ImageButton currPaint, drawBtn, eraseBtn, newBtn, saveBtn, opacityBtn; 
    //sizes 
    private float smallBrush, mediumBrush, largeBrush; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     //get drawing view 
     drawView = (DrawingView)findViewById(R.id.drawing); 

//  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
//   drawView.setBackground(getResources().getDrawable(R.drawable.background, null)); 
//  } 
//  else 
//   drawView.setBackground(getResources().getDrawable(R.drawable.background)); 
     //get the palette and first color button 
     LinearLayout paintLayout = (LinearLayout)findViewById(R.id.paint_colors); 
     currPaint = (ImageButton)paintLayout.getChildAt(0); 
     currPaint.setImageDrawable(getResources().getDrawable(R.drawable.paint_pressed)); 

     //sizes from dimensions 
     smallBrush = getResources().getInteger(R.integer.small_size); 
     mediumBrush = getResources().getInteger(R.integer.medium_size); 
     largeBrush = getResources().getInteger(R.integer.large_size); 

     //draw button 
     drawBtn = (ImageButton)findViewById(R.id.draw_btn); 
     drawBtn.setOnClickListener(this); 

     //set initial size 
     drawView.setBrushSize(smallBrush); 

     //erase button 
     eraseBtn = (ImageButton)findViewById(R.id.erase_btn); 
     eraseBtn.setOnClickListener(this); 

     //new button 
     newBtn = (ImageButton)findViewById(R.id.new_btn); 
     newBtn.setOnClickListener(this); 

     //save button 
     saveBtn = (ImageButton)findViewById(R.id.save_btn); 
     saveBtn.setOnClickListener(this); 

     //opacity 
     opacityBtn = (ImageButton)findViewById(R.id.opacity_btn); 
     opacityBtn.setOnClickListener(this); 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     // Inflate the menu; this adds items to the action bar if it is present. 
//  getMenuInflater().inflate(R.menu.main, menu); 
     return true; 
    } 

    //user clicked paint 
    public void paintClicked(View view){ 
     //use chosen color 

     //set erase false 
     drawView.setErase(false); 
     drawView.setPaintAlpha(100); 
     drawView.setBrushSize(drawView.getLastBrushSize()); 

     if(view!=currPaint){ 
      ImageButton imgView = (ImageButton)view; 
      String color = view.getTag().toString(); 
      drawView.setColor(color); 
      //update ui 
      imgView.setImageDrawable(getResources().getDrawable(R.drawable.paint_pressed)); 
      currPaint.setImageDrawable(getResources().getDrawable(R.drawable.paint)); 
      currPaint=(ImageButton)view; 
     } 
    } 

    @Override 
    public void onClick(View view){ 

     if(view.getId()==R.id.draw_btn){ 
      //draw button clicked 
      final Dialog brushDialog = new Dialog(this); 
      brushDialog.setTitle("Brush size:"); 
      brushDialog.setContentView(R.layout.brush_chooser); 
      //listen for clicks on size buttons 
      ImageButton smallBtn = (ImageButton)brushDialog.findViewById(R.id.small_brush); 
      smallBtn.setOnClickListener(new OnClickListener(){ 
       @Override 
       public void onClick(View v) { 
        drawView.setErase(false); 
        drawView.setBrushSize(smallBrush); 
        drawView.setLastBrushSize(smallBrush); 
        brushDialog.dismiss(); 
       } 
      }); 
      ImageButton mediumBtn = (ImageButton)brushDialog.findViewById(R.id.medium_brush); 
      mediumBtn.setOnClickListener(new OnClickListener(){ 
       @Override 
       public void onClick(View v) { 
        drawView.setErase(false); 
        drawView.setBrushSize(mediumBrush); 
        drawView.setLastBrushSize(mediumBrush); 
        brushDialog.dismiss(); 
       } 
      }); 
      ImageButton largeBtn = (ImageButton)brushDialog.findViewById(R.id.large_brush); 
      largeBtn.setOnClickListener(new OnClickListener(){ 
       @Override 
       public void onClick(View v) { 
        drawView.setErase(false); 
        drawView.setBrushSize(largeBrush); 
        drawView.setLastBrushSize(largeBrush); 
        brushDialog.dismiss(); 
       } 
      }); 
      //show and wait for user interaction 
      brushDialog.show(); 
     } 
     else if(view.getId()==R.id.erase_btn){ 
      //switch to erase - choose size 
      final Dialog brushDialog = new Dialog(this); 
      brushDialog.setTitle("Eraser size:"); 
      brushDialog.setContentView(R.layout.brush_chooser); 
      //size buttons 
      ImageButton smallBtn = (ImageButton)brushDialog.findViewById(R.id.small_brush); 
      smallBtn.setOnClickListener(new OnClickListener(){ 
       @Override 
       public void onClick(View v) { 
        drawView.setErase(true); 
        drawView.setBrushSize(smallBrush); 
        brushDialog.dismiss(); 
       } 
      }); 
      ImageButton mediumBtn = (ImageButton)brushDialog.findViewById(R.id.medium_brush); 
      mediumBtn.setOnClickListener(new OnClickListener(){ 
       @Override 
       public void onClick(View v) { 
        drawView.setErase(true); 
        drawView.setBrushSize(mediumBrush); 
        brushDialog.dismiss(); 
       } 
      }); 
      ImageButton largeBtn = (ImageButton)brushDialog.findViewById(R.id.large_brush); 
      largeBtn.setOnClickListener(new OnClickListener(){ 
       @Override 
       public void onClick(View v) { 
        drawView.setErase(true); 
        drawView.setBrushSize(largeBrush); 
        brushDialog.dismiss(); 
       } 
      }); 
      brushDialog.show(); 
     } 
     else if(view.getId()==R.id.new_btn){ 
      //new button 
      AlertDialog.Builder newDialog = new AlertDialog.Builder(this); 
      newDialog.setTitle("New drawing"); 
      newDialog.setMessage("Start new drawing (you will lose the current drawing)?"); 
      newDialog.setPositiveButton("Yes", new DialogInterface.OnClickListener(){ 
       public void onClick(DialogInterface dialog, int which){ 
        drawView.startNew(); 
        dialog.dismiss(); 
       } 
      }); 
      newDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener(){ 
       public void onClick(DialogInterface dialog, int which){ 
        dialog.cancel(); 
       } 
      }); 
      newDialog.show(); 
     } 
     else if(view.getId()==R.id.save_btn){ 
      //save drawing 
      AlertDialog.Builder saveDialog = new AlertDialog.Builder(this); 
      saveDialog.setTitle("Save drawing"); 
      saveDialog.setMessage("Save drawing to device Gallery?"); 
      saveDialog.setPositiveButton("Yes", new DialogInterface.OnClickListener(){ 
       public void onClick(DialogInterface dialog, int which){ 
        //save drawing 
        drawView.setDrawingCacheEnabled(true); 
        //attempt to save 
        String imgSaved = MediaStore.Images.Media.insertImage(
          getContentResolver(), drawView.getDrawingCache(), 
          UUID.randomUUID().toString()+".png", "drawing"); 
        //feedback 
        if(imgSaved!=null){ 
         Toast savedToast = Toast.makeText(getApplicationContext(), 
           "Drawing saved to Gallery!", Toast.LENGTH_SHORT); 
         savedToast.show(); 
        } 
        else{ 
         Toast unsavedToast = Toast.makeText(getApplicationContext(), 
           "Oops! Image could not be saved.", Toast.LENGTH_SHORT); 
         unsavedToast.show(); 
        } 
        drawView.destroyDrawingCache(); 
       } 
      }); 
      saveDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener(){ 
       public void onClick(DialogInterface dialog, int which){ 
        dialog.cancel(); 
       } 
      }); 
      saveDialog.show(); 
     } 
     else if(view.getId()==R.id.opacity_btn){ 
      //launch opacity chooser 
      final Dialog seekDialog = new Dialog(this); 
      seekDialog.setTitle("Opacity level:"); 
      seekDialog.setContentView(R.layout.opacity_chooser); 
      //get ui elements 
      final TextView seekTxt = (TextView)seekDialog.findViewById(R.id.opq_txt); 
      final SeekBar seekOpq = (SeekBar)seekDialog.findViewById(R.id.opacity_seek); 
      //set max 
      seekOpq.setMax(100); 
      //show current level 
      int currLevel = drawView.getPaintAlpha(); 
      seekTxt.setText(currLevel+"%"); 
      seekOpq.setProgress(currLevel); 
      //update as user interacts 
      seekOpq.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { 

       @Override 
       public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 
        seekTxt.setText(Integer.toString(progress)+"%"); 
       } 

       @Override 
       public void onStartTrackingTouch(SeekBar seekBar) {} 

       @Override 
       public void onStopTrackingTouch(SeekBar seekBar) {} 

      }); 
      //listen for clicks on ok 
      Button opqBtn = (Button)seekDialog.findViewById(R.id.opq_ok); 
      opqBtn.setOnClickListener(new OnClickListener(){ 
       @Override 
       public void onClick(View v) { 
        drawView.setPaintAlpha(seekOpq.getProgress()); 
        seekDialog.dismiss(); 
       } 
      }); 
      //show dialog 
      seekDialog.show(); 
     } 
    } 

} 
+1

Похоже, что у вас была правильная идея в какой-то момент; установив изображение в качестве фона. Разве это не сработало для вас? –

+0

@MikeM. это не работает для меня :(, фон просто отображает все белые, если я использую этот метод. –

+1

Как вы это понимаете? Он белый, даже когда вы рисуете, или просто когда вы пытаетесь его сохранить? –

ответ

0

То, что решило мою проблему, состояло в том, чтобы установить изображение в качестве фона поверхности с помощью setBackgroundDrawable. Затем, при сохранении, мне просто нужно было получить кеш рисования с холста, который затем включает фоновое изображение.

1

Вы реализовали все вещи в правильном направлении, но я просто хочу предложить вам попробовать следующий код, может быть, это поможет вам ,

public void clearCanvas() { 
     drawPath.reset(); 
     invalidate(); 
} 

попробовать этот метод вместо setErase(), приведенный выше метод используется, чтобы очистить путь, который вы создали с помощью прикосновения. Вы можете сбросить все значения до значений по умолчанию в этом методе.

+0

На самом деле дело не в очистке холста, а в стирании, чтобы установить кисть на цвет для стирания путей при перетаскивании. –

+0

Это не приведет к стиранию холста на самом деле, но он очистит путь, который у вас есть. –

+0

Спасибо за информацию, которая может быть полезна для отмены. –

Смежные вопросы