i want to set image on white canvas and want to draw on that image i don't know how to do that. i tried all possible method, but not work. this is my code help me if u want any other code then tell me. and please help me......
package com.example.drowingdemo;
import android.content.Context;
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.graphics.drawable.Drawable;
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;
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);
}
// draw the view - will be called after touch event
#Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
canvas.drawPath(drawPath, drawPaint);
}
// 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(canvasBitmap);
}
// 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.drowingdemo");
// 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;
if (erase)
drawPaint
.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
else
drawPaint.setXfermode(null);
}
// 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);
}
}
Through the code, I didn't see which line loads an image.
In your code, Bitmap is set for Canvas in method onSizeChanged, but the bitmap is an empty bitmap, you may try the code to load image
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
canvasBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.your_image) //-->here load your image
.copy(Bitmap.Config.ARGB_8888, true);
drawCanvas = new Canvas(canvasBitmap);//-->set bitmap
}
In addition, drawPath.reset() is called before invalidate(), do not reset path before onDraw(),
#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);
invalidate();
break;
case MotionEvent.ACTION_UP:
drawPath.lineTo(touchX, touchY);
drawPath = new Path();//--> use a new path after ACTION_UP
break;
default:
return false;
}
// redraw
drawCanvas.drawPath(drawPath, drawPaint);//--> Draw on canvasBitmap
invalidate();
return true;
}
#Override
protected void onDraw(Canvas canvas)
{
canvas.drawBitmap(canvasBitmap, 0, 0, null);//--> draw canvasBitmap on canvas
...
}
Related
I have a custom ImageView where user can draw using some colors.
I load image from server then allow user to draw on top of it.
When i load the next image , i want the previously drawn colors to be gone before user can draw again.
I tried many thing from internet but not able to achieve the same.
below is code for custom ImageView:
public class DrawingView extends androidx.appcompat.widget.AppCompatImageView {
//drawing path
static Path drawPath;
//drawing and canvas paint
private Paint drawPaint, canvasPaint;
//initial color
static int paintColor = 0xFFFFFFFF;
//stroke width
private float STROKE_WIDTH = 5f;
//canvas
private Canvas drawCanvas;
//canvas bitmap
private Bitmap canvasBitmap;
//eraser mode
private boolean erase = false;
private boolean cc = false;
//constructor
public DrawingView(Context context, AttributeSet attrs) {
super(context, attrs);
setupDrawing();
setErase(erase);
}
private void setupDrawing() {
drawPath = new Path();
drawPaint = new Paint();
drawPaint.setColor(paintColor);
drawPaint.setAntiAlias(true);
drawPaint.setStrokeWidth(STROKE_WIDTH);
drawPaint.setStyle(Paint.Style.STROKE);
drawPaint.setStrokeJoin(Paint.Join.ROUND);
drawPaint.setStrokeCap(Paint.Cap.ROUND);
canvasPaint = new Paint(Paint.DITHER_FLAG);
}
//*************************************** View assigned size ****************************************************
#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(canvasBitmap);
}
public void setPaintColor(int paintColor) {
this.paintColor = paintColor;
setupDrawing();
}
public void setImageOnImageview(Bitmap canvasBitmap) {
this.canvasBitmap = canvasBitmap;
}
#Override
public void setImageResource(int resId) {
super.setImageResource(resId);
}
public void setErase(boolean isErase) {
erase = isErase;
drawPaint = new Paint();
if (erase) {
setupDrawing();
int srcColor = getResources().getColor(R.color.white);
PorterDuff.Mode mode = PorterDuff.Mode.CLEAR;
PorterDuffColorFilter porterDuffColorFilter = new PorterDuffColorFilter(srcColor, mode);
drawPaint.setColorFilter(porterDuffColorFilter);
drawPaint.setColor(srcColor);
drawPaint.setXfermode(new PorterDuffXfermode(mode));
} else {
setupDrawing();
}
}
//************************************ draw view *************************************************************
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (cc) {
canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
canvas.drawPath(drawPath, drawPaint);
cc = false;
} else {
canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
canvas.drawPath(drawPath, drawPaint);
}
}
public void clearCanvas() {
setupDrawing();
setErase(false);
cc = true;
invalidate();
}
//*************************** respond to touch interaction **************************************************
#Override
public boolean onTouchEvent(MotionEvent event) {
canvasPaint.setColor(paintColor);
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:
drawCanvas.drawPath(drawPath, drawPaint);
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;
}
//*********************************** return current alpha ***********************************************
public int getPaintAlpha() {
return Math.round((float) STROKE_WIDTH / 255 * 100);
}
//************************************** set alpha ******************************************************
public void setPaintAlpha(int newAlpha) {
STROKE_WIDTH = Math.round((float) newAlpha / 100 * 255);
drawPaint.setStrokeWidth(newAlpha);
}
}
I tried many solutions like clear path or clear paint.
Could any please help me with this ?
I assume you want to remove the drawn color on first image upon loading the new image
I think you can draw the color over canvas
Canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
or reset the path itself
Path.reset();
I am working on a painting app, with undo/redo function and would like to add eraser function.
Code for MainActivity
case R.id.undoBtn:
doodleView.onClickUndo();
break;
case R.id.redoBtn:
doodleView.onClickRedo();
break;
case R.id.eraserBtn:
Constants.mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); break;
DrawView
// Drawing Part
private Bitmap mBitmap;
private Paint mBitmapPaint;
private Canvas mCanvas;
private Path mPath;
private int selectedColor = Color.BLACK;
private int selectedWidth = 5;
private ArrayList<Path> paths = new ArrayList<Path>();
private ArrayList<Path> undonePaths = new ArrayList<Path>();
private Map<Path, Integer> colorsMap = new HashMap<Path, Integer>();
private Map<Path, Integer> widthMap = new HashMap<Path, Integer>();
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
Context context_new;
public DoodleView(Context c, AttributeSet attrs)
{
super(c, attrs);
context_new = c;
setFocusable(true);
setFocusableInTouchMode(true);
setLayerType(View.LAYER_TYPE_SOFTWARE, null); // for solely removing the black eraser
mPath = new Path();
mCanvas = new Canvas();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
Constants.mPaint = new Paint();
Constants.mPaint.setAntiAlias(true); // smooth edges of drawn line
Constants.mPaint.setDither(true);
Constants.mPaint.setColor(Color.BLACK); // default color is black
Constants.mPaint.setStyle(Paint.Style.STROKE); // solid line
Constants.mPaint.setStrokeJoin(Paint.Join.ROUND);
Constants.mPaint.setStrokeWidth(20); // set the default line width
Constants.mPaint.setStrokeCap(Paint.Cap.ROUND); // rounded line ends
Constants.mPaint.setXfermode(null);
Constants.mPaint.setAlpha(0xFF);
}
#Override
public void onSizeChanged(int w, int h, int oldW, int oldH)
{
super.onSizeChanged(w, h, oldW, oldH);
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Constants.DRAW_W = w;
Constants.DRAW_H = h;
Log.d("TAG", "onSizeChanged!!!" + Constants.DRAW_W + Constants.DRAW_H + Constants.SCREEN_W + Constants.SCREEN_H);
// bitmap.eraseColor(Color.WHITE); // erase the BitMap with white
}
#Override
protected void onDraw(Canvas canvas)
{
canvas.drawBitmap(mBitmap, 0, 0, null); // draw the background screen
for (Path p : paths)
{
Constants.mPaint.setColor(colorsMap.get(p));
Constants.mPaint.setStrokeWidth(widthMap.get(p));
canvas.drawPath(p, Constants.mPaint);
}
Constants.mPaint.setColor(selectedColor);
Constants.mPaint.setStrokeWidth(selectedWidth);
canvas.drawPath(mPath, Constants.mPaint);
}
#Override
public boolean onTouchEvent(MotionEvent event)
{
float x = event.getX();
float y = event.getY();
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touch_move(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up();
invalidate();
break;
}
return true;
}
private void touch_start(float x, float y)
{
undonePaths.clear();
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
}
private void touch_move(float x, float y)
{
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE)
{
mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
mX = x;
mY = y;
startdrawing = true;
}
}
private void touch_up()
{
mPath.lineTo(mX, mY);
mCanvas.drawPath(mPath, Constants.mPaint);
paths.add(mPath);
colorsMap.put(mPath,selectedColor);
widthMap.put(mPath,selectedWidth);
mPath = new Path();
}
public void onClickUndo()
{
if (paths.size()>0)
{
undonePaths.add(paths.remove(paths.size()-1));
invalidate();
}
else Toast.makeText(getContext(), R.string.toast_nothing_to_undo, Toast.LENGTH_SHORT).show();
}
public void onClickRedo()
{
if (undonePaths.size()>0)
{
paths.add(undonePaths.remove(undonePaths.size()-1));
invalidate();
}
else
Toast.makeText(getContext(), R.string.toast_nothing_to_redo, Toast.LENGTH_SHORT).show();
}
public void setDrawingColor(int color)
{
selectedColor = color;
Constants.mPaint.setColor(color);
}
public int getDrawingColor()
{
return Constants.mPaint.getColor();
}
Question:
Normal painting and undo / redo can be performed perfectly. However, the eraser does not work.
After pressing (touch_start) the eraser button and touch the screen, all the previous drawn line immediately turn black.
When using the eraser upon touch_move , the eraser itself is drawing black lines, even though it was on CLEAR mode.
Upon touch_up, All other drawn lines maintained at black color. The "erased" area was also in black color. However, when drawing a new path subsequently, the original line turned to their original color, the area "erased" by the eraser turn its color to the last color chosen and the paths retained in the View.
How could the code on eraser be written in a proper way? (keeping undo / redo)
Thanks a lot in advance!
It's hard to answer your question, but. I'd implement the erase functionality as follows:
The erase function will by simple white path. So the erase mode means that you are drawing white path which will be wider than the drawing path. This way you will be able to select even the width of the eraser and the undo/redo functionality will stay the same.
Try this type of application with samsung spen sdk, all this funtions are simplified there.
SPen Sdk Tutorial
or
Make your erase paint color to your background color.
// Please use this is erasure concept . This is working and tested.
public void addErasure(){
drawView.setErase(true);
drawView.setBrushSize(20);
}
public void addPencil(){
drawView.setErase(false);
drawView.setBrushSize(20);
drawView.setLastBrushSize(20);
}
/// this my drawing view. you can add this view into your main layout.
public class DrawingView extends View {
//drawing path
private Path drawPath;
//drawing and canvas paint
private Paint drawPaint, canvasPaint;
//initial color
private int paintColor = 0xFF660000;
//canvas
private Canvas drawCanvas;
//canvas bitmap
private Bitmap canvasBitmap;
//brush sizes
private float brushSize, lastBrushSize;
//erase flag
private boolean erase=false;
private boolean isFirstTime = false;
public DrawingView(Context context, AttributeSet attrs){
super(context, attrs);
//setBackgroundColor(Color.CYAN);
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);
//canvasPaint.setColor(Color.GREEN);
}
//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);
Bitmap canvasBackGroundBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
canvasBackGroundBitmap = getResizedBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.pop_up_big_bg),h,w);
// drawCanvas = new Canvas(canvasBackGroundBitmap);
// drawCanvas.drawColor(Color.GREEN);
setBackgroundDrawable(new BitmapDrawable(canvasBackGroundBitmap));
drawCanvas = new Canvas(canvasBitmap);
}
public static Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth) {
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// CREATE A MATRIX FOR THE MANIPULATION
Matrix matrix = new Matrix();
// RESIZE THE BIT MAP
matrix.postScale(scaleWidth, scaleHeight);
// "RECREATE" THE NEW BITMAP
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false);
return resizedBitmap;
}
//draw the view - will be called after touch event
#Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(canvasBitmap, 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);
drawCanvas.drawPath(drawPath, drawPaint);
drawPath.reset();
drawPath.moveTo(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();
paintColor = Color.parseColor(newColor);
drawPaint.setColor(paintColor);
}
//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;
if(erase) {
drawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
}else {
drawPaint.setXfermode(null);
}
}
//start new drawing
public void startNew(){
drawCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
invalidate();
}
}
Try this solution - works great with undo/redo as well:
private float blur = 0F;
case R.id.eraserBtn:
Constants.mPaint.setColor(Color.WHITE); // or whatever color to match canvas color
Constants.mPaint.setShadowLayer(this.blur, 0F, 0F, Color.WHITE);
With this solution, no need to set:
Constants.mPaint.setXfermode(null);
Welcome guys,
I have problem with custom drawing view (Fingerprint)
I'm using
drawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
The problem is it draws black lines then it removes the drawing.
How to disable this black line and enable it to transparent
My code is:
import android.annotation.SuppressLint;
import android.graphics.PorterDuff;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
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.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.view.MotionEvent;
public class DrawingView extends View {
// drawing path
private Path drawPath;
// drawing and canvas paint
private Paint drawPaint, canvasPaint, drawCirclePaint;
// initial color
public int paintColor = Color.BLACK;
// canvas
private Canvas drawCanvas;
// canvas bitmap
private Bitmap canvasBitmap;
private float brushSize;
private boolean startedEditing = false;
private int width, height;
public boolean isLined = false;
public DrawingView(Context context, AttributeSet attrs) {
super(context, attrs);
setupDrawing();
}
public boolean isStartedEditing() {
return startedEditing;
}
public void setBackColor(int color) {
this.setBackgroundColor(color);
}
public int getBackColor() {
int colorID;
try {
ColorDrawable color = (ColorDrawable) this.getBackground();
colorID = color.getColor();
} catch (Exception e) {
colorID = Color.WHITE;
}
return colorID;
}
public void setupDrawing() {
brushSize = 4;
drawPath = new Path();
drawPaint = new Paint();
drawPaint.setColor(paintColor);
drawPaint.setAntiAlias(true);
drawPaint.setStyle(Paint.Style.STROKE);
drawPaint.setStrokeJoin(Paint.Join.ROUND);
drawPaint.setStrokeCap(Paint.Cap.ROUND);
drawPaint.setStrokeWidth(brushSize);
drawCirclePaint = new Paint();
drawCirclePaint.setColor(paintColor);
drawCirclePaint.setStyle(Paint.Style.FILL);
drawCirclePaint.setStrokeJoin(Paint.Join.ROUND);
drawCirclePaint.setStrokeCap(Paint.Cap.ROUND);
drawCirclePaint.setStrokeWidth(brushSize / 4);
canvasPaint = new Paint(Paint.DITHER_FLAG);
}
public void setBrushSize(float newSize) {
float pixelAmount = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, newSize, getResources()
.getDisplayMetrics());
brushSize = pixelAmount;
drawPaint.setStrokeWidth(brushSize);
}
public void setBrushColor(int newColor) {
drawPaint.setColor(newColor);
drawCirclePaint.setColor(newColor);
}
public int getBrushColor() {
return (drawPaint.getColor() == Color.WHITE) ? Color.BLACK : drawPaint
.getColor();
}
#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(canvasBitmap);
width = w;
height = h;
// setLinedBackground();
}
#SuppressLint("NewApi")
public void setLinedBackground(boolean setOrRemove) {
if (setOrRemove) {
isLined = true;
// Lined Background
// Initialize lined background
Bitmap linedBackground = Bitmap.createBitmap(width, height,
Bitmap.Config.ARGB_8888);
Canvas linedBackgroundCanvas = new Canvas(linedBackground);
// Set back white color
linedBackgroundCanvas.drawColor(Color.WHITE);
final float scale = DrawingView.this.getResources()
.getDisplayMetrics().density;
int pixels = (int) (50 * scale + 0.5f);
for (int i = 1, j = 0; j < drawCanvas.getHeight() / (pixels); i++, j++) {
Paint myPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
myPaint.setStrokeWidth((int) (1 * scale + 0.5f));
myPaint.setColor(Color.argb(60, 168, 168, 168));
linedBackgroundCanvas.drawLine(5, i * pixels,
drawCanvas.getWidth() - 5, i * pixels, myPaint);
}
BitmapDrawable ob = new BitmapDrawable(
DrawingView.this.getResources(), linedBackground);
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN) {
this.setBackgroundDrawable(ob);
} else {
this.setBackground(ob);
}
} else {
isLined = false;
// Lined Background
// Initialize lined background
setBackColor(Color.WHITE);
}
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
canvas.drawPath(drawPath, drawPaint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
AddDrawingNote.moreLayout.setVisibility(View.GONE);
startedEditing = true;
float touchX = event.getX();
float touchY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
drawCanvas.drawPoint(touchX, touchY, drawCirclePaint);
drawPath.moveTo(touchX, touchY);
break;
case MotionEvent.ACTION_MOVE:
drawPath.lineTo(touchX, touchY);
break;
case MotionEvent.ACTION_UP:
drawCanvas.drawPath(drawPath, drawPaint);
drawPath.reset();
break;
default:
return false;
}
invalidate();
return true;
}
public void setErase() {
drawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
}
}
and the xml
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="10dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:background="#drawable/drawingnote_main_layout_bg"
android:orientation="vertical"
android:weightSum="100" >
<ImageView
android:id="#+id/drawingView_back"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:layout_margin="1dp"
android:background="#FFFF00"/>
<ibrahim.radwan.qnotes.DrawingView
android:id="#+id/add_drawing_note_drawing"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:layout_margin="1dp"
android:background="#00ffffff" />
</RelativeLayout>
Any ideas :)
Yo, I figured this out. Just set the paint color to the background of your view.
I can get Erasing to Work but cannot get Undo to Work
And I can get Undo to Work but Erasing cannot work.
I have tried multiple times to figure out why it is doing this. But i am having no success.
Here is my Drawing class:
import java.util.ArrayList;
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.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;
public class DrawingView extends View {
//drawing path
private Path drawPath;
//drawing and canvas paint
private Paint drawPaint, canvasPaint;
//initial color
private int paintColor = 0xFF660000;
//canvas
private Canvas drawCanvas;
private Canvas backUp;
//canvas bitmap
private Bitmap canvasBitmap;
private Bitmap backUpBitmap;
private float brushSize;
private boolean erasing;
private ArrayList<Path> paths = new ArrayList<Path>();
private ArrayList<Integer> paints = new ArrayList<Integer>();
public DrawingView(Context context, AttributeSet attrs) {
super(context, attrs);
setupDrawingView();
}
private void setupDrawingView() {
drawPath = new Path();
drawPaint = new Paint();
drawPaint.setColor(paintColor);
drawPaint.setAntiAlias(true);
drawPaint.setDither(true);
drawPaint.setStyle(Paint.Style.STROKE);
drawPaint.setStrokeJoin(Paint.Join.ROUND);
drawPaint.setStrokeCap(Paint.Cap.ROUND);
canvasPaint = new Paint(Paint.DITHER_FLAG);
brushSize = 5;
drawPaint.setStrokeWidth(brushSize);
erasing = false;
}
#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);
backUpBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
drawCanvas = new Canvas(canvasBitmap);
backUp = new Canvas(backUpBitmap);
}
#Override
protected void onDraw(Canvas canvas) {
for(int i = 0; i < paths.size(); i++) {
Integer j = paints.get(i);
Paint p = new Paint();
p.setColor(j.intValue());
p.setAntiAlias(true);
p.setDither(true);
p.setStyle(Paint.Style.STROKE);
p.setStrokeJoin(Paint.Join.ROUND);
p.setStrokeCap(Paint.Cap.ROUND);
p.setXfermode(null);
p.setStrokeWidth(5);
canvas.drawPath(paths.get(i), p);
}
drawPaint.setColor(paintColor);
if(erasing)
drawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawPath(drawPath, drawPaint);
canvas.drawBitmap(canvasBitmap, 0, 0, drawPaint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float touchX = event.getX();
float touchY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
drawPath.moveTo(touchX, touchY);
backUp.drawBitmap(canvasBitmap, 0, 0, null);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
drawPath.lineTo(touchX, touchY);
invalidate();
break;
case MotionEvent.ACTION_UP:
drawCanvas.drawPath(drawPath, drawPaint);
if(!erasing) {
paints.add(paintColor);
paths.add(drawPath);
drawPath = new Path();
}
drawPath.reset();
invalidate();
//drawPath = new Path();
break;
default:
return false;
}
invalidate();
return true;
}
public void setColor(String newColor) {
invalidate();
paintColor = Color.parseColor(newColor);
drawPaint.setColor(paintColor);
}
public void setColor(int color) {
invalidate();
drawPaint.setColor(color);
}
public void setErase(boolean erase){
Mode x = PorterDuff.Mode.CLEAR;
erasing = erase;
if(erase) {
drawPaint.setXfermode(new PorterDuffXfermode(x));
} else {
drawPaint.setXfermode(null);
drawPaint.setColor(0xFF000000);
}
drawCanvas.drawPath(drawPath, drawPaint);
}
public void reset() {
drawCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
invalidate();
drawPath.reset();
paths.clear();
paints.clear();
}
public void setBrushSize(float newSize) {
brushSize = newSize;
drawPaint.setStrokeWidth(newSize);
}
public void undo () {
if (paths.size() > 0) {
Path undoPath = paths.get(paths.size()-1);
undoPath.reset();
paths.remove(paths.size() -1);
paints.remove(paints.size()-1);
drawCanvas.drawBitmap(canvasBitmap, 0, 0, null);
invalidate();
} else {
Toast.makeText(getContext(), "Cannot Undo", Toast.LENGTH_SHORT).show();
}
}
public int getPaths() {
return paths.size();
}
}
create a new path every time you draw and save it on a stack, undo by poping paths from the stack
I'm doing a simple drawing app, and so far I've managed to control the opacity and size of the brush.
Now I'm trying to set some kind of hardness, like in Photoshop, but I looked at the documentation and Paint doesn't seem to have something like that.
In case it's relevant, I'm following this
tutorial.
public class DrawingView extends View {
//drawing path
private Path drawPath;
//drawing and canvas paint
private Paint drawPaint, canvasPaint;
//initial color
private int paintColor = 0xFF660000;
//canvas
private Canvas drawCanvas;
//canvas bitmap
private Bitmap canvasBitmap;
//brush sizes
private float brushSize, lastBrushSize;
//erase flag
private boolean erase=false;
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);
}
//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(canvasBitmap);
}
//draw the view - will be called after touch event
#Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(canvasBitmap, 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();
paintColor = Color.parseColor(newColor);
drawPaint.setColor(paintColor);
}
//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;
}
public void setErase(boolean isErase){
erase=isErase;
if(erase) drawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
else drawPaint.setXfermode(null);
}
//start new drawing
public void startNew(){
drawCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
invalidate();
}
}
So, how can I set a Paint's hardness?
Thanks a lot!
Found it!
private Paint drawPaint= new Paint();
drawPaint.setMaskFilter(new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL));
Where the first parameter of BlurMaskFilter is the radius of the blur :)