I have created a simple drawing app, in which i am using a seek bar to get stroke width. But as soon as i change the stroke width, the width of complete drawing changes. Same happens when i change the pen color. How to individually assign stroke attributes to each path?
I have tried many answers but could not get the correct result.
I have tried storing the path and the respective paint associated with it and then drawing it. but that too didn't work.
public class MainActivity extends AppCompatActivity {
View mView;
private Paint mPaint;
SeekBar mSeekbar;
int penColor = Color.BLACK;
int bgColor = Color.WHITE;
int StrokeWidth = 12;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LinearLayout layout = (LinearLayout) findViewById(R.id.myDrawing);
mView = new DrawingView(this);
mSeekbar = (SeekBar) findViewById(R.id.seek);
mSeekbar.getProgressDrawable().setColorFilter(Color.RED, PorterDuff.Mode.SRC_IN);
mSeekbar.getThumb().setColorFilter(Color.RED, PorterDuff.Mode.SRC_IN);
layout.addView(mView, new ActionBar.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT));
((DrawingView) mView).init();
penSize();
}
public void penSize() {
mSeekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
((DrawingView) mView).changePenSize(StrokeWidth);
StrokeWidth = i;
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
((DrawingView) mView).changePenSize(StrokeWidth);
}
});
}
class DrawingView extends View {
private Path path;
private Bitmap mBitmap;
private Canvas mCanvas;
public DrawingView(Context context) {
super(context);
path = new Path();
mBitmap = Bitmap.createBitmap(820, 480, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
this.setBackgroundColor(bgColor);
mPaint = new Paint();
mPaint.setDither(true);
mPaint.setColor(penColor);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(StrokeWidth);
}
public void changePenSize(int size) {
StrokeWidth = size;
mPaint.setStrokeWidth(StrokeWidth);
invalidate();
}
public void init() {
mPaint = new Paint();
mPaint.setDither(true);
mPaint.setColor(penColor);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(StrokeWidth);
}
public void setBGColor(int color) {
bgColor = color;
this.setBackgroundColor(bgColor);
invalidate();
}
public void ClearPath() {
path.reset();
bgColor = Color.WHITE;
penColor = Color.BLACK;
init();
invalidate();
}
public void changePenColor() {
mPaint.setColor(penColor);
invalidate();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float touchX = event.getX();
float touchY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
path.moveTo(touchX, touchY);
break;
case MotionEvent.ACTION_MOVE:
path.lineTo(touchX, touchY);
break;
case MotionEvent.ACTION_UP:
mCanvas.drawPath(path, mPaint);
break;
default:
return false;
}
invalidate();
return true;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawPath(path, mPaint);
}
}
#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;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
File myDir = new File(Environment.getExternalStorageDirectory(),
"Drawings");
myDir.mkdirs();
Date now = new Date();
String fname = "image" + now.getDate() + now.getSeconds() + ".jpg";
File file = new File(myDir, fname);
//noinspection SimplifiableIfStatement
if (id == R.id.clear) {
AlertDialog.Builder alert = new AlertDialog.Builder(MainActivity.this);
alert.setTitle("Do you really want to clear ?\nYou can save before clearing.");
alert.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
((DrawingView) mView).ClearPath();
Toast.makeText(MainActivity.this, "Done", Toast.LENGTH_SHORT).show();
}
});
alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
}
});
alert.show();
return true;
} else if (id == R.id.bgColor) {
bgColor();
} else if (id == R.id.penColor) {
penColor();
} else if (id == R.id.screenshot) {
takeScreenshot();
return true;
}
return super.onOptionsItemSelected(item);
}
private void penColor() {
AmbilWarnaDialog dialog = new AmbilWarnaDialog(MainActivity.this, Color.BLACK, new AmbilWarnaDialog.OnAmbilWarnaListener() {
#Override
public void onOk(AmbilWarnaDialog dialog, int color) {
penColor = color;
((DrawingView) mView).changePenColor();
}
#Override
public void onCancel(AmbilWarnaDialog dialog) {
}
});
dialog.show();
}
private void bgColor() {
AmbilWarnaDialog dialog = new AmbilWarnaDialog(MainActivity.this, Color.BLACK, new AmbilWarnaDialog.OnAmbilWarnaListener() {
#Override
public void onOk(AmbilWarnaDialog dialog, int color) {
bgColor = color;
((DrawingView) mView).setBGColor(bgColor);
}
#Override
public void onCancel(AmbilWarnaDialog dialog) {
}
});
dialog.show();
}
private void takeScreenshot() {
mView.setDrawingCacheEnabled(true);
String filename= UUID.randomUUID().toString() + ".png";
String imgSaved = MediaStore.Images.Media.insertImage(
getContentResolver(), mView.getDrawingCache(),
filename, "drawing");
if (imgSaved != null) {
Toast.makeText(getApplicationContext(),
"Drawing saved to Gallery! ", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(),
"Oops! Image could not be saved.", Toast.LENGTH_SHORT).show();
}
mView.destroyDrawingCache();
}
}
class DrawingView extends View {
ArrayList<DrawingPath> paths;
private DrawingPath drawingPath;
private Bitmap mBitmap;
private Canvas mCanvas;
public DrawingView(Context context) {
super(context);
paths = new ArrayList<>();
mBitmap = Bitmap.createBitmap(820, 480, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
this.setBackgroundColor(bgColor);
mPaint = new Paint();
mPaint.setDither(true);
mPaint.setColor(penColor);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(StrokeWidth);
}
public void changePenSize(int size) {
StrokeWidth = size;
mPaint.setStrokeWidth(StrokeWidth);
}
public void init() {
mPaint = new Paint();
mPaint.setDither(true);
mPaint.setColor(penColor);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(StrokeWidth);
}
public void setBGColor(int color) {
bgColor = color;
this.setBackgroundColor(bgColor);
invalidate();
}
public void ClearPath() {
paths.clear();
bgColor = Color.WHITE;
penColor = Color.BLACK;
init();
invalidate();
}
public void changePenColor() {
mPaint.setColor(penColor);
invalidate();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float touchX = event.getX();
float touchY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
drawingPath = new DrawingPath(mPaint.getStrokeWidth());
paths.add(drawingPath);
drawingPath.path.moveTo(touchX, touchY);
break;
case MotionEvent.ACTION_MOVE:
drawingPath.path.lineTo(touchX, touchY);
break;
case MotionEvent.ACTION_UP:
mCanvas.drawPath(drawingPath.path, mPaint);
break;
default:
return false;
}
invalidate();
return true;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (DrawingPath drawingPath : paths) {
mPaint.setStrokeWidth(drawingPath.strokeWidth);
canvas.drawPath(drawingPath.path, mPaint);
}
}
}
class DrawingPath {
Path path;
float strokeWidth;
DrawingPath(float strokeWidth) {
path = new Path();
this.strokeWidth = strokeWidth;
}
}
I hope this will help. You can other properties like color,style, etc to DrawingPath model.
Related
Canvas Painting is not reset when Click ,It is reset when I am drawing again on canvas after click the clear button.............................................................................................................................................................................................................................................................................................................................................................................
HERE IS MY CODE
public class Practice extends FragmentActivity {
private RelativeLayout relativeLayout;
private Paint paint;
ImageView back;
private View view;
private Path path2;
private Bitmap bitmap;
private Canvas canvas;
private Button button;
public int width, height;
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_practice);
back = findViewById(R.id.back);
relativeLayout = (RelativeLayout) findViewById(R.id.relativelayout1);
back.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onBackPressed();
}
});
button = (Button) findViewById(R.id.button);
view = new SketchSheetView(Practice.this);
paint = new Paint();
path2 = new Path();
relativeLayout.addView(view, new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT));
paint.setDither(true);
paint.setColor(Color.parseColor("#FFFFFF"));
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.MITER);
paint.setStrokeCap(Paint.Cap.BUTT);
paint.setStrokeWidth(5);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
path2.reset();
}
});
}
class SketchSheetView extends View {
public SketchSheetView(Context context) {
super(context);
bitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_4444);
canvas = new Canvas(bitmap);
this.setBackground(getResources().getDrawable(R.drawable.ic_brush_black_24dp));
}
private ArrayList<DrawingClass> DrawingClassArrayList = new ArrayList<DrawingClass>();
#Override
public boolean onTouchEvent(MotionEvent event) {
Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
DrawingClass pathWithPaint = new DrawingClass();
canvas.drawPath(path2, paint);
if (event.getAction() == MotionEvent.ACTION_DOWN) {
this.setBackground(null);
vibrator.vibrate(500);
path2.moveTo(event.getX(), event.getY());
path2.lineTo(event.getX(), event.getY());
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
this.setBackground(null);
path2.lineTo(event.getX(), event.getY());
vibrator.vibrate(500);
pathWithPaint.setPath(path2);
pathWithPaint.setPaint(paint);
DrawingClassArrayList.add(pathWithPaint);
}
invalidate();
return true;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (DrawingClassArrayList.size() > 0) {
canvas.drawPath(
DrawingClassArrayList.get(DrawingClassArrayList.size() - 1).getPath(),
DrawingClassArrayList.get(DrawingClassArrayList.size() - 1).getPaint()
);
}
}
}
public class DrawingClass {
Path DrawingClassPath;
Paint DrawingClassPaint;
public Path getPath() {
return DrawingClassPath;
}
public void setPath(Path path) {
this.DrawingClassPath = path;
}
public Paint getPaint() {
return DrawingClassPaint;
}
public void setPaint(Paint paint) {
this.DrawingClassPaint = paint;
}
}
#Override
public void onBackPressed() {
super.onBackPressed();
}
I have a problem with my drawing app, in that the mask filters are using a lot of paramaters and lisiting it in to the array list. I think everytime I draw the maskfilter gets added to the arraylist and then the canvas draws the whole array list from scratch. Or it is the problem with onDraw please give me suggestions for performance improvements.
public class PaintingActivity extends AppCompatActivity {
private PaintView paintView;
private Toolbar mTopToolbar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_paint);
mTopToolbar = (Toolbar) findViewById(R.id.my_toolbar);
setSupportActionBar(mTopToolbar);
paintView = (PaintView) findViewById(R.id.paintView);
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
paintView.init(metrics);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.draw_menu, menu);
return super.onCreateOptionsMenu(menu);
}
private void colorPicker() {
final Context context = PaintingActivity.this;
ColorPickerDialogBuilder
.with(context)
.setTitle("Choose color")
.initialColor(DEFAULT_COLOR)
.wheelType(ColorPickerView.WHEEL_TYPE.CIRCLE)
.density(12)
.setOnColorSelectedListener(new OnColorSelectedListener() {
#Override
public void onColorSelected(int selectedColor) {
Toast.makeText(context, "onColorSelected: 0x" + Integer.toHexString(selectedColor), Toast.LENGTH_SHORT).show();
}
})
.setPositiveButton("ok", new ColorPickerClickListener() {
#Override
public void onClick(DialogInterface dialog, int selectedColor, Integer[] allColors) {
//changeBackgroundColor(selectedColor);
}
})
.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
})
.build()
.show();
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()) {
case R.id.normal:
paintView.normal();
return true;
case R.id.emboss:
paintView.emboss();
return true;
case R.id.blur:
paintView.blur();
return true;
case R.id.color_picker:
colorPicker();
return true;
case R.id.clear:
paintView.clear();
return true;
}
return super.onOptionsItemSelected(item);
}
}
Then my PaintView
public class PaintView extends View {
public static int BRUSH_SIZE = 20;
public static final int DEFAULT_COLOR = Color.RED;
public static final int DEFAULT_BG_COLOR = Color.WHITE;
private static final float TOUCH_TOLERANCE = 4;
private float mX, mY;
private Path mPath;
private Paint mPaint;
private ArrayList<FingerPath> paths = new ArrayList<>();
private int currentColor;
private int backgroundColor = DEFAULT_BG_COLOR;
private int strokeWidth;
private boolean emboss;
private boolean blur;
private MaskFilter mEmboss;
private MaskFilter mBlur;
private Bitmap mBitmap;
private Canvas mCanvas;
private Paint mBitmapPaint = new Paint(Paint.DITHER_FLAG);
public PaintView(Context context) {
this(context, null);
}
public PaintView(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(DEFAULT_COLOR);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setXfermode(null);
mPaint.setAlpha(0xff);
mEmboss = new EmbossMaskFilter(new float[] {1, 1, 1}, 0.4f, 6, 3.5f);
mBlur = new BlurMaskFilter(5, BlurMaskFilter.Blur.NORMAL);
}
public void init(DisplayMetrics metrics) {
int height = metrics.heightPixels;
int width = metrics.widthPixels;
mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
currentColor = DEFAULT_COLOR;
strokeWidth = BRUSH_SIZE;
}
public void normal() {
emboss = false;
blur = false;
}
public void emboss() {
emboss = true;
blur = false;
}
public void blur() {
emboss = false;
blur = true;
}
public void clear() {
backgroundColor = DEFAULT_BG_COLOR;
paths.clear();
normal();
invalidate();
}
#Override
protected void onDraw(Canvas canvas) {
canvas.save();
mCanvas.drawColor(backgroundColor);
for (FingerPath fp : paths) {
mPaint.setColor(fp.color);
mPaint.setStrokeWidth(fp.strokeWidth);
mPaint.setMaskFilter(null);
if (fp.emboss)
mPaint.setMaskFilter(mEmboss);
else if (fp.blur)
mPaint.setMaskFilter(mBlur);
mCanvas.drawPath(fp.path, mPaint);
}
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.restore();
}
private void touchStart(float x, float y) {
mPath = new Path();
FingerPath fp = new FingerPath(currentColor, emboss, blur, strokeWidth, mPath);
paths.add(fp);
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
}
private void touchMove(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;
}
}
private void touchUp() {
mPath.lineTo(mX, mY);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN :
touchStart(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE :
touchMove(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP :
touchUp();
invalidate();
break;
}
return true;
}
}
Also my layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.lolow.asserty.asserty.paint.PaintingActivity"
android:background="#color/lightGrey">
<android.support.v7.widget.Toolbar
android:id="#+id/my_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:elevation="4dp" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.lolow.asserty.asserty.paint.PaintView
android:id="#+id/paintView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="40dp"
android:layout_marginBottom="100dp"
android:background="#drawable/paint_view_border"/>
</RelativeLayout>
</RelativeLayout>
This is also my path class:
public class FingerPath {
public int color;
public boolean emboss;
public boolean blur;
public int strokeWidth;
public Path path;
public FingerPath(int color, boolean emboss, boolean blur, int strokeWidth, Path path) {
this.color = color;
this.emboss = emboss;
this.blur = blur;
this.strokeWidth = strokeWidth;
this.path = path;
}
}
There are few other questions,similar to mine, that I have followed and implemented their answers in every possible manner but that doesnt seem to work on my code. I'm close to the solution but seem to be missing on something. Kindly help and I request not to mark the question as duplicate.
here's the mainActivity:
public class MainActivity extends Activity implements View.OnClickListener {
// private ArrayList<Path> paths = new ArrayList<Path>();
// private ArrayList<Path> undonePaths = new ArrayList<Path>();
private Button btnUndo;
public 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);
drawView = (DrawingView) findViewById(R.id.drawing);
//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 = 10;
mediumBrush = 20;
largeBrush = 30;
//draw button
drawBtn = (ImageButton) findViewById(R.id.draw_btn);
drawBtn.setOnClickListener(this);
//set initial size
drawView.setBrushSize(mediumBrush);
//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);
btnUndo = (Button) findViewById(R.id.btnUndo);
btnUndo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
drawView.undo();
}
});
}
#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 View.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 View.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 View.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 View.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 View.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 View.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.btnUndo) {
//undo drawing
{
//drawView.setErase(true);
drawView.undo();
/* if (paths.size() > 0) {
// drawView.setErase(true);
undonePaths.add(paths.remove(paths.size() - 1));
view.invalidate();
} else {
Toast.makeText(getBaseContext(), "undo isnt working", Toast.LENGTH_SHORT).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 SeekBar.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 View.OnClickListener() {
#Override
public void onClick(View v) {
drawView.setPaintAlpha(seekOpq.getProgress());
seekDialog.dismiss();
}
});
//show dialog
seekDialog.show();
}
}
}
DrawingView.java:
(Undo function is at the bottom of this class)
public class DrawingView extends View{
private ArrayList<Path> paths = new ArrayList<Path>();
private ArrayList<Path> undonePaths = new ArrayList<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();
}
private void setupDrawing() {
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);
// paths.add(drawPath);
}
#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) {
for (Path path : paths) {
canvas.drawPath(path, drawPaint);
}
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();
//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;
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);
}
//define undo func
public void undo() {
if (paths.size() > 0) {
undonePaths.add(paths.remove(paths.size() - 1));
invalidate();
} else {
Toast.makeText(getContext(), "undo isnt working wth", Toast.LENGTH_SHORT).show();
}
}
}
I had a similar problem with this earlier today, This is a fairly old ticket so I am not sure if you are interested still... however someone else might be.
I think the issue is that you only ever use one instance of path - its kinda odd but the path isn't just point A-B
I think what you need to do is to make new paths prior to putting them into your collection - Selvin said this in his comment.
For example you could do something like this;
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:
//Make a new instance of DrawPath
drawPath = new Path();
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;
}
when you do path rest I suspect it is clearing all the lines that are drawn - this is because they are all one path (despite the fact several on-touch events have made them).
if this doesnt work let me know what actually is the problem - is the line not appearing etc...
I'm using this app to draw free lines in android
DrawerView.java
public class DrawerView extends View {
public static Paint paint;
Paint paint2 = new Paint();
public Path path = new Path();
public Path circlePath = new Path();
public static int lineCol = Color.BLUE;
public static boolean isTouchable = false;
public LayoutParams params;
public DrawerView(Context context, AttributeSet attrs){
super(context, attrs);
paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(lineCol);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(4f);
}
public void onButtonPress(){
// resets the screen
path.reset();
// Calls the onDraw() method
postInvalidate();
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawPath(path, paint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (!isTouchable){
return false;
} else {
// Gives you x and y coordinates on the Event.
float pointX = event.getX();
float pointY = event.getY();
// Checks for the event that occurs
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
path.moveTo(pointX, pointY);
return true;
case MotionEvent.ACTION_MOVE:
path.lineTo(pointX, pointY);
circlePath.reset();
circlePath.addCircle(pointX, pointY, 30, Path.Direction.CW);
break;
case MotionEvent.ACTION_UP:
circlePath.reset();
break;
default:
return false;
}
postInvalidate();
return true;
}
}
}
DrawLines.java
public class DrawLines extends Activity {
DrawerView myView;
public Button btnReset;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.draw_line);
myView = (DrawerView)findViewById(R.id.custView);
btnReset = (Button) findViewById(R.id.button1);
btnReset.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
// resets the screen
myView.path.reset();
// Calls the onDraw() method
myView.postInvalidate();
}
});
}
}
draw_line.xml
<Button
android:id="#+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Clear" />
<com.example.drawline.DrawerView
android:id="#+id/custView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/button1"
android:layout_margin="5dp"
custom:lineColor="#ff0099" />
It works well with me but I want to be able to select the color of line, so I added a button in draw_line.xml that when press it show a dialog that asks the user to select color. this is the code of dialog
public void openSelectColorDialog()
{
final Dialog d = new Dialog(this);
d.setTitle("Select Color");
d.setContentView(R.layout.military_list);
int image[] = { R.drawable.black, R.drawable.blue, R.drawable.yellow};
ArrayList<HashMap<String, String>> objArayList = new ArrayList<HashMap<String, String>>();
for (int i = 0; i < image.length; i++) {
HashMap<String, String> listData = new HashMap<String, String>();
listData.put("image", Integer.toString(image[i]));
objArayList.add(listData);
}
String[] from = { "image"};
int[] to = { R.id.list_image };
SimpleAdapter listAdapter = new SimpleAdapter(this, objArayList,
R.layout.military_list_item, from, to);
ListView lst1 = (ListView) d.findViewById(android.R.id.list);
lst1.setAdapter(listAdapter);
lst1.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parentView, View childView, int position, long id) {
if (position == 0) {
// the code of color line
d.dismiss();
} else if (position == 1) {
// the code of blue line
d.dismiss();
} else {
// the code of yellow line
d.dismiss();
}
myView.postInvalidate();
}
});
d.show();
}
What is the code I have to add to make the color like what I selected ?
consider if I write this code
DrawerView.paint.setColor(Color.BLACK);
the whole line changes its color to the selected color and this is not what I want.
I want that the color of the new line is like what I selected and keep the old lines with its colors.
Hope anyone got my mean.
Thanks in advance.
Edit
the new code is:
ColoredPath.java
public class ColoredPath {
private Paint paint;
private Path path = new Path();
private int color;
public ColoredPath() {
paint = new Paint();
color = Color.BLACK;
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(4f);
paint.setAntiAlias(true);
paint.setColor(color);
}
public ColoredPath(int color) {
paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(4f);
paint.setAntiAlias(true);
paint.setColor(color);
}
public void setColor(int color){
this.color = color;
}
public int getColor(){
return color;
}
public void setPaint(Paint paint){
this.paint = paint;
}
public Paint getPaint() {
return paint;
}
public void setPath(Path path){
this.path = path;
}
public Path getPath() {
return path;
}
}
DrawerView.java
public class DrawerView extends View {
public Path circlePath = new Path();
public static int LINE_COLOR = 0;
public static boolean isTouchable = false;
public List<ColoredPath> paths = new ArrayList<ColoredPath>();
public ColoredPath currentPath;
public DrawerView(Context context, AttributeSet attrs){
super(context, attrs);
currentPath = new ColoredPath();
paths.add(currentPath);
}
public void newLine(int color){
System.out.println("in newLine method");
currentPath = new ColoredPath(color);
paths.add(currentPath);
//postInvalidate();
}
public void onButtonPress(){
// resets the screen
currentPath.getPath().reset();
// Calls the onDraw() method
postInvalidate();
}
#Override
protected void onDraw(Canvas canvas) {
System.out.println("size of paths: "+paths.size());
canvas.drawPath(currentPath.getPath(), currentPath.getPaint());
for(int i = 0; i < paths.size(); ++i) {
//ColoredPath coloredPath = paths.get(i);
canvas.drawPath(currentPath.getPath(), currentPath.getPaint());
}
}
public Path getLastPath() {
Path path = new Path();
for(int i = 0; i < paths.size(); ++i) {
path.addPath(paths.get(i).getPath());
}
return path;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (!isTouchable){
return false;
} else {
// Gives you x and y coordinates on the Event.
float pointX = event.getX();
float pointY = event.getY();
// Checks for the event that occurs
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
currentPath.getPath().moveTo(pointX, pointY);
//getLastPath().moveTo(pointX, pointY);
return true;
case MotionEvent.ACTION_MOVE:
currentPath.getPath().lineTo(pointX, pointY);
//getLastPath().lineTo(pointX, pointY);
circlePath.reset();
circlePath.addCircle(pointX, pointY, 30, Path.Direction.CW);
break;
case MotionEvent.ACTION_UP:
circlePath.reset();
break;
default:
return false;
}
postInvalidate();
return true;
}
}
}
and in MainActivity.java
if (position == 1) {
// blue
myView.newLine(Color.BLUE);
d.dismiss();
}
this works well and colors the lines but when I select any color it leads to remove the last line and I want all lines with there colors.
Because Path itself doesn't contain any information about it's color (color is managed by Canvas) I would suggest you to create new pair of (Path, Paint) for every new path with different paint and use only current pair in onTouch event. So here is some code which illustrate this idea
public class ColoredPath {
private Paint paint;
private Path path;
public ColoredPath(Paint paint, Path path) {
this.paint = paint;
this.path = path;
}
public Paint getPaint() {
return paint;
}
public Path getPath() {
return path;
}
}
private List<ColoredPath> paths = new ArrayList<ColoredPath>();
public DrawerView(Context context, AttributeSet attrs){
super(context, attrs);
//custom paint can be used here
paths.add(new ColoredPath(new Paint(), new Path()));
}
/////
#Override
protected void onDraw(Canvas canvas) {
for(ColoredPath coloredPath : paths) {
canvas.drawPath(coloredPath.getPath(), coloredPath.getPaint());
}
}
Where paths is List<ColoredPath>. And also you need field like ColoredPath currentPath.
I am currently developing a coloring app for the kids. Created a canvas of an image for coloring. The image is a PNG and I am trying to color the image so the image does not get covered by the paint or color. I am very close in building the app but the problem is that I am not getting the tip of coloring the image in a way so that the image remains on the front and the color on the back
Here is my code
public class FingerPaint extends Activity {
LinearLayout mainContainer;
LinearLayout buttonContainer;
LinearLayout.LayoutParams ![enter image description here][1]btnParams;
Button btnText, btnSketch, btnColor, btnUndo, btnRedo, btnDone,btnClear;
// MyView drawView;
DrawingPanel drawView;
int lastColor = 0xFFFF0000;
public static final int SUCCESS = 200;
private final String TAG = getClass().getSimpleName();
private String textToDraw = null;
private boolean isTextModeOn = false;
private Canvas mCanvas;
private Path mPath;
private Paint mPaint, mBitmapPaint;
private ArrayList<PathPoints> paths = new ArrayList<PathPoints>();
private ArrayList<PathPoints> undonePaths = new ArrayList<PathPoints>();
private Bitmap mBitmap;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
generateViews();
}
public static void displayAlert(Context context, String msg) {
AlertDialog.Builder alert = new AlertDialog.Builder(context);
alert.setMessage(context.getString(R.string.app_name));
alert.setMessage(msg);
alert.setPositiveButton(context.getString(R.string.btn_ok),
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
}
});
alert.show();
}
private void generateViews() {
btnDone = new Button(this);
btnDone.setLayoutParams(new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
btnDone.setText(getString(R.string.btn_done));
btnText = new Button(this);
btnClear = new Button(this);
btnSketch = new Button(this);
btnColor = new Button(this);
btnUndo = new Button(this);
btnRedo = new Button(this);
mainContainer = new LinearLayout(this);
mainContainer.setLayoutParams(new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
mainContainer.setOrientation(LinearLayout.VERTICAL);
buttonContainer = new LinearLayout(this);
buttonContainer.setLayoutParams(new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
buttonContainer.setOrientation(LinearLayout.HORIZONTAL);
btnParams = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT, 1);
btnText.setText("Text");
btnText.setLayoutParams(btnParams);
btnClear.setText("Clear");
btnClear.setLayoutParams(btnParams);
btnSketch.setText("Sketch");
btnSketch.setLayoutParams(btnParams);
btnColor.setText("Color");
btnColor.setLayoutParams(btnParams);
btnUndo.setText("Undo");
btnUndo.setLayoutParams(btnParams);
btnRedo.setText("Redo");
btnRedo.setLayoutParams(btnParams);
buttonContainer.addView(btnText);
buttonContainer.addView(btnClear);
buttonContainer.addView(btnSketch);
buttonContainer.addView(btnColor);
buttonContainer.addView(btnUndo);
buttonContainer.addView(btnRedo);
drawView = new DrawingPanel(this, lastColor);
drawView.setDrawingCacheEnabled(true);
drawView.measure(
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
drawView.layout(0, 0, drawView.getMeasuredWidth(),
drawView.getMeasuredHeight());
drawView.buildDrawingCache(true);
drawView.setLayoutParams(new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT, 1));
mainContainer.addView(btnDone);
mainContainer.addView(drawView);
mainContainer.addView(buttonContainer);
setContentView(mainContainer);
btnSketch.setSelected(true);
btnText.setOnClickListener(new OnClickListener() {
//text
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
resetButtons();
btnText.setSelected(true);
AlertDialog.Builder alert = new AlertDialog.Builder(
FingerPaint.this);
alert.setMessage(getString(R.string.msg_enter_text_to_draw));
final EditText edText = new EditText(FingerPaint.this);
alert.setView(edText);
alert.setPositiveButton(R.string.btn_ok,
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog,
int which) {
// TODO Auto-generated method stub
if (edText.getText().toString().length() > 0) {
textToDraw = edText.getText().toString();
isTextModeOn = true;
displayAlert(FingerPaint.this,
getString(R.string.msg_tap_image));
} else {
displayAlert(
FingerPaint.this,
getString(R.string.msg_enter_text_to_draw));
}
}
});
alert.setNegativeButton(R.string.btn_cancel,
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog,
int which) {
// TODO Auto-generated method stub
isTextModeOn = false;
}
});
alert.show();
}
});
/// clear
btnClear.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
//mBitmap.eraseColor(Color.TRANSPARENT);
mPath.reset();
paths.removeAll(paths);
undonePaths.removeAll(undonePaths);
drawView.invalidate();
}
});
////sketch
btnSketch.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
resetButtons();
btnSketch.setSelected(true);
isTextModeOn = false;
}
});
//color
/* btnColor.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
AmbilWarnaDialog dialog = new AmbilWarnaDialog(
FingerPaint.this, lastColor,
new OnAmbilWarnaListener() {
#Override
public void onOk(AmbilWarnaDialog dialog, int color) {
// color is the color selected by the user.
colorChanged(color);
}
#Override
public void onCancel(AmbilWarnaDialog dialog) {
// cancel was selected by the user
}
});
dialog.show();
}
});*/
//undo
btnUndo.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
drawView.onClickUndo();
}
});//redo
btnRedo.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
drawView.onClickRedo();
}
});
//done
btnDone.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
/*Log.v(TAG, "Here");
Bitmap editedImage = Bitmap.createBitmap(drawView
.getDrawingCache());
editedImage = Bitmap.createScaledBitmap(editedImage, 200, 300,
true);
if (editedImage != null) {
Intent intent = new Intent();
//intent.putExtra(ChooseActivity.BITMAP, editedImage);
// AddReportItemActivity.mPhoto =
// drawView.getDrawingCache();
setResult(SUCCESS, intent);
finish();
}
}*/
AlertDialog.Builder editalert = new AlertDialog.Builder(FingerPaint.this);
editalert.setTitle("Please Enter the name with which you want to Save");
final EditText input = new EditText(FingerPaint.this);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.FILL_PARENT);
input.setLayoutParams(lp);
editalert.setView(input);
editalert.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
String name= input.getText().toString();
Bitmap bitmap = drawView.getDrawingCache();
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
File file = new File("mnt/sdcard/"+name+".png");
try
{
if(!file.exists())
{
file.createNewFile();
}
FileOutputStream ostream = new FileOutputStream(file);
bitmap.compress(CompressFormat.PNG, 10, ostream);
ostream.close();
drawView.invalidate();
}
catch (Exception e)
{
e.printStackTrace();
}finally
{
drawView.setDrawingCacheEnabled(false);
}
}
});
editalert.show();
}
});
}
public void resetButtons() {
btnText.setSelected(false);
btnClear.setSelected(false);
btnSketch.setSelected(false);
btnColor.setSelected(false);
btnUndo.setSelected(false);
btnRedo.setSelected(false);
}
public class DrawingPanel extends View implements OnTouchListener {
private int color;
public int x, y;
public DrawingPanel(Context context, int color) {
super(context);
this.color = color;
setFocusable(true);
setFocusableInTouchMode(true);
this.setOnTouchListener(this);
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(color);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.MITER);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(15);
mPaint.setTextSize(30);
//mPaint.setStyle(Style s);
mPath = new Path();
paths.add(new PathPoints(mPath, color, false));
mCanvas = new Canvas();
}
public void colorChanged(int color) {
this.color = color;
mPaint.setColor(color);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// mBitmap = AddReportItemActivity.mPhoto;
//mBitmap = getIntent().getExtras().getParcelable(ChooseActivity.BITMAP);
mBitmap = BitmapFactory.decodeResource(
getApplicationContext().getResources(),
R.drawable.images);
// targetImage.setImageBitmap(srcBitmapLocal);
float xscale = (float) w / (float) mBitmap.getWidth();
float yscale = (float) h / (float) mBitmap.getHeight();
if (xscale > yscale) // make sure both dimensions fit (use the
// smaller scale)
xscale = yscale;
float newx = (float) w * xscale;
float newy = (float) h * xscale; // use the same scale for both
// dimensions
// if you want it centered on the display (black borders)
mBitmap = Bitmap.createScaledBitmap(mBitmap, this.getWidth(),
this.getHeight(), true);
// mCanvas = new Canvas(mBitmap);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
for (PathPoints p : paths) {
mPaint.setColor(p.getColor());
Log.v("", "Color code : " + p.getColor());
if (p.isTextToDraw()) {
canvas.drawText(p.textToDraw, p.x, p.y, mPaint);
} else {
canvas.drawPath(p.getPath(), mPaint);
}
}
}
private float mX, mY;
private static final float TOUCH_TOLERANCE = 0;
Point p=new Point();
private void touch_start(float x, float y) {
p.x=(int)x;
p.y=(int)y;
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;
int xx=Math.round(mX);
int yy=Math.round(mY);
}
}
private void touch_up() {
mPath.lineTo(mX, mY);
// commit the path to our offscreen
mCanvas.drawPath(mPath, mPaint);
// kill this so we don't double draw
mPath = new Path();
paths.add(new PathPoints(mPath, color, false));
}
private void drawText(int x, int y) {
Log.v(TAG, "Here");
Log.v(TAG, "X " + x + " Y " + y);
this.x = x;
this.y = y;
paths.add(new PathPoints(color, textToDraw, true, x, y));
// mCanvas.drawText(textToDraw, x, y, mPaint);
}
#Override
public boolean onTouch(View arg0, MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (!isTextModeOn) {
touch_start(x, y);
invalidate();
}
break;
case MotionEvent.ACTION_MOVE:
if (!isTextModeOn) {
touch_move(x, y);
invalidate();
}
break;
case MotionEvent.ACTION_UP:
if (isTextModeOn) {
drawText((int) x, (int) y);
invalidate();
} else {
touch_up();
invalidate();
}
break;
}
return true;
}
public void onClickUndo() {
if (paths.size() > 0) {
undonePaths.add(paths.remove(paths.size() - 1));
invalidate();
} else {
}
// toast the user
}
public void onClickRedo() {
if (undonePaths.size() > 0) {
paths.add(undonePaths.remove(undonePaths.size() - 1));
invalidate();
} else {
}
// toast the user
}
}
public void colorChanged(int color) {
// TODO Auto-generated method stub
lastColor = color;
drawView.colorChanged(lastColor);
}
class PathPoints {
private Path path;
// private Paint mPaint;
private int color;
private String textToDraw;
private boolean isTextToDraw;
private int x, y;
public PathPoints(Path path, int color, boolean isTextToDraw) {
this.path = path;
this.color = color;
this.isTextToDraw = isTextToDraw;
}
public PathPoints(int color, String textToDraw, boolean isTextToDraw,
int x, int y) {
this.color = color;
this.textToDraw = textToDraw;
this.isTextToDraw = isTextToDraw;
this.x = x;
this.y = y;
}
public Path getPath() {
return path;
}
public void setPath(Path path) {
this.path = path;
}
public int getColor() {
return color;
}
public void setColor(int color) {
this.color = color;
}
public String getTextToDraw() {
return textToDraw;
}
public void setTextToDraw(String textToDraw) {
this.textToDraw = textToDraw;
}
public boolean isTextToDraw() {
return isTextToDraw;
}
public void setTextToDraw(boolean isTextToDraw) {
this.isTextToDraw = isTextToDraw;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
}
in your :
#Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
}
add these lines before canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.save();
canvas.drawColor(0xff000000);
hope it will help