I'm trying to draw on the my .png image, but it works very slow. If I'm drawing on the imageView without .png file it works fine. How can I solve this? As I understand I need to prevent "A LOT of drawings all the time", how can I realise this?
code:
public class Draw
extends Activity{
DrawingView dv ;
private Paint mPaint;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dv = new DrawingView(this);
setContentView(dv);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(Color.GREEN);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(12);
}
public class DrawingView extends View {
public int width;
public int height;
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
private Paint mBitmapPaint;
Context context;
private Paint circlePaint;
private Path circlePath;
public DrawingView(Context c) {
super(c);
context=c;
mPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
circlePaint = new Paint();
circlePath = new Path();
circlePaint.setAntiAlias(true);
circlePaint.setColor(Color.BLUE);
circlePaint.setStyle(Paint.Style.STROKE);
circlePaint.setStrokeJoin(Paint.Join.MITER);
circlePaint.setStrokeWidth(4f);
}
#Override
protected 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);
mCanvas = new Canvas(mBitmap);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Bitmap bm = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory() + "/MANUAL/workflow" + "/img.png");
int targetWidth = bm.getWidth() / 1;
int targetHeight = bm.getHeight() / 1;
Matrix matrix = new Matrix();
matrix.postScale(0.7f, 0.65f);
Bitmap size = Bitmap.createBitmap(bm, 0, 0, targetWidth, targetHeight, matrix, true);
Paint paint = new Paint();
paint.setColor(Color.RED);
canvas.drawBitmap(size, 0, 0, paint);
canvas.drawBitmap( mBitmap, 0, 0, mBitmapPaint);
canvas.drawPath( mPath, mPaint);
canvas.drawPath( circlePath, circlePaint);
}
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
private void touch_start(float x, float 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;
circlePath.reset();
circlePath.addCircle(mX, mY, 30, Path.Direction.CW);
}
}
private void touch_up() {
mPath.lineTo(mX, mY);
circlePath.reset();
// commit the path to our offscreen
mCanvas.drawPath(mPath, mPaint);
// kill this so we don't double draw
mPath.reset();
}
#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;
}
}
Your onDraw() method should look like this:
#Override
protected void onDraw(Canvas canvas) {
paint.setColor(Color.RED);
canvas.drawBitmap(size, 0, 0, paint);
canvas.drawBitmap( mBitmap, 0, 0, mBitmapPaint);
canvas.drawPath( mPath, mPaint);
canvas.drawPath( circlePath, circlePaint);
}
All Bitmap decoding and resizing should be done outside (in the constructor or only when the view is resized), there is no need to decode and resize it every time when the result will be same every time.
Related
I need help with this thing
I draw line on canvas and i need to be able to modify the position after it's been drawn. I search and try a lot of things, but no one seems that it works
I want to select one of the ends of the line and dragging them in another position
Can someone give me and advice?
Please try this.In this you can draw and edit the line.
class Drawing extends View{
private Canvas mCanvas = null;
private Path mPath = null;
private Paint mBitmapPaint = null;
private Bitmap mBitmap = null;
private Bitmap bit=null;
private Paint mPaint = null;
private MainActivity baseMainActivity = null;
public interface onDrawingViewSingleTap{
void onDrawingViewTap(float x , float y);
}
public Drawing(Context c) {
super(c);
baseMainActivity=(MainActivity) c;
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(Color.YELLOW);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(6);//This sets the width of signature
Display display =baseMainActivity.getWindowManager().getDefaultDisplay();
mBitmap = Bitmap.createBitmap(display.getWidth(), display.getHeight(), Bitmap.Config.ARGB_8888);// 320*480 // For setting size of screen to draw Bitmap
mPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
mCanvas = new Canvas(mBitmap);
onDraw(mCanvas);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
#Override
protected void onDraw(Canvas canvas) {
try{
canvas.drawColor(Color.TRANSPARENT);//Color.WHITE //To change background color of Application
if(bit!=null)
canvas.drawBitmap(bit, 0, 0, mBitmapPaint);
else
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
}catch(Exception e){}
if(bit==null)
canvas.drawPath(mPath, mPaint);
bit=null;
}
private float mX, mY;
private void touch_start(float x, float y) {
mPath.reset();
mPath.moveTo(x, y);
mX = x+1;
mY = y+1;
}
private void touch_upline(float x,float y) {
mPath.lineTo(mX, mY);
mCanvas.drawLine(mX, mY, x, y, mPaint);
mPath.reset();
}
#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:
eraseAll();
touch_upline(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_upline(x,y);
invalidate();
break;
}
return true;
}
public void eraseAll()
{
mBitmap.eraseColor(android.graphics.Color.TRANSPARENT);
mCanvas = new Canvas(mBitmap);
}
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
RelativeLayout relativeLayout= (RelativeLayout) (findViewById(R.id.mainLayout));
relativeLayout.addView(new Drawing(this));
}
}
I'm letting the user to do painting in my app.The app will show some options on the screen once the whole screen is painted. And I want to check if the user has painted the whole screen.
Is there a way to detect if the user has painted the whole screen? Like an event triggered after the whole screen is painted.
Following is my code for painting:
public class DrawingView extends View {
public int width;
public int height;
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
private Paint mBitmapPaint;
Context context;
private Paint circlePaint;
private Path circlePath;
Stack mXStack;
Stack mYStack;
public DrawingView(Context c) {
super(c);
context = c;
mPath = new Path();
mXStack = new Stack();
mYStack = new Stack();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
circlePaint = new Paint();
circlePath = new Path();
circlePaint.setAntiAlias(true);
circlePaint.setColor(Color.BLUE);
circlePaint.setStyle(Paint.Style.STROKE);
circlePaint.setStrokeJoin(Paint.Join.MITER);
circlePaint.setStrokeWidth(50f);
}
#Override
protected 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);
mCanvas = new Canvas(mBitmap);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.drawPath(mPath, mPaint);
canvas.drawPath(circlePath, circlePaint);
}
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
private void touch_start(float x, float 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;
circlePath.reset();
circlePath.addCircle(mX, mY, 30, Path.Direction.CW);
}
}
private void touch_up() {
mPath.lineTo(mX, mY);
circlePath.reset();
// commit the path to our offscreen
mCanvas.drawPath(mPath, mPaint);
// kill this so we don't double draw
mPath.reset();
}
#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;
}
}
I want to create a drawing app, and it works clearly but it is still far away from my goal.
Here's my code:
public class MainActivity extends Activity {
DrawingView dv;
private Paint mPaint;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dv = new DrawingView(this);
setContentView(dv);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(Color.BLUE);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(5);
}
public class DrawingView extends View {
public int width;
public int height;
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
private Paint mBitmapPaint;
Context context;
private Paint circlePaint;
private Path circlePath;
public DrawingView(Context c) {
super(c);
context = c;
mPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
circlePaint = new Paint();
circlePath = new Path();
circlePaint.setAntiAlias(true);
circlePaint.setColor(Color.RED);
circlePaint.setStyle(Paint.Style.STROKE);
circlePaint.setStrokeJoin(Paint.Join.MITER);
circlePaint.setStrokeWidth(4f);
}
#Override
protected 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);
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.asd) //-->here load your image
.copy(Bitmap.Config.ARGB_8888, true);
mCanvas = new Canvas(mBitmap);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.drawPath(mPath, mPaint);
canvas.drawPath(circlePath, circlePaint);
}
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
private void touch_start(float x, float 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;
circlePath.reset();
circlePath.addCircle(mX, mY, 30, Path.Direction.CW);
}
}
private void touch_up() {
mPath.lineTo(mX, mY);
circlePath.reset();
// commit the path to our offscreen
mCanvas.drawPath(mPath, mPaint);
// kill this so we don't double draw
mPath.reset();
}
#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;
}
}
}
public class FingerPaintActivity extends Activity
implements ColorPickerDialog.OnColorChangedListener{
MyView mv;
AlertDialog dialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mv= new MyView(this);
mv.setDrawingCacheEnabled(true);
mv.setBackgroundResource(R.drawable.afor);//set the back ground if you wish to
setContentView(mv);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(0xFFFF0000);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(20);
mEmboss = new EmbossMaskFilter(new float[] { 1, 1, 1 },
0.4f, 6, 3.5f);
mBlur = new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL);
}
private Paint mPaint;
private MaskFilter mEmboss;
private MaskFilter mBlur;
public void colorChanged(int color) {
mPaint.setColor(color);
}
public class MyView extends View {
private static final float MINP = 0.25f;
private static final float MAXP = 0.75f;
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
private Paint mBitmapPaint;
Context context;
public MyView(Context c) {
super(c);
context=c;
mPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
}
#Override
protected 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);
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.asd) //-->here load your image
.copy(Bitmap.Config.ARGB_8888, true);
mCanvas = new Canvas(mBitmap);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.drawPath(mPath, mPaint);
}
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
private void touch_start(float x, float y) {
//showDialog();
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;
}
}
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.reset();
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SCREEN));
//mPaint.setMaskFilter(null);
}
#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;
}
}
}
This is what my app looks like:
I want to change color draw from blue to brown. I changed mPaint.setColor(Color.BROWN); and it failed.
If you check my preview app, you'll see that I want to create a business logic where: If user is drawing and it's not completed, the app will show a message like "sorry you have not finished the drawing" and I still look for the way to do it. I don't know if it's possible, is it?
Try using the following line:
mPaint.setColor(ContextCompat.getColor(context, R.color.your_color));
I presume that your main question is how to change color programmatically, right?
just change:
mPaint.setColor(Color.BROWN);
to:
mPaint.setColor(getResources().getColor(R.color.Brown));
I think it can help you
In my app, I have extended the class to view. After finishing the draw(Handout from touch), if I will perform touch event, It should not be invoke on the extended view class. It will perform touch event function of Main Activity.
Code :
public class DrawOnImage extends View {
public static Bitmap DrawBitmap;
private Canvas mCanvas;
private Path mPath;
private Paint DrawBitmapPaint;
private Paint mPaint;
#SuppressWarnings("deprecation")
public DrawOnImage(Context c) {
super(c);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(getResources().getColor(android.R.color.holo_green_dark));
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(20);
mPath = new Path();
DrawBitmapPaint = new Paint(Paint.DITHER_FLAG);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
DrawBitmap = Bitmap.createBitmap(w, h,
Bitmap.Config.ARGB_4444);
mCanvas = new Canvas(DrawBitmap);
}
#Override
protected void onDraw(Canvas canvas) {
setDrawingCacheEnabled(true);
canvas.drawBitmap(DrawBitmap, 0, 0, DrawBitmapPaint);
canvas.drawPath(mPath, mPaint);
canvas.drawRect(mY, 0, mY, 0, DrawBitmapPaint);
}
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
private void touch_start(float x, float 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;
}
}
private void touch_up() {
mPath.lineTo(mX, mY);
mCanvas.drawPath(mPath, mPaint);
mPath.reset();
}
#Override
public boolean onTouchEvent(#NonNull MotionEvent event) {
if(DrawBitmap == null) {
setVisibility(INVISIBLE);
}else {
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;
}
}
ParameterGetSet.drawingBitmap = DrawBitmap;
return true;
}
}
Why it doesn't work ? I'm trying to "paint" where i put my finger, to write something. For example, when i am trying to make a C he looks like this: http://postimg.org/image/5obyif4o1/ ........................................................................
public class BlackPixel extends View implements OnTouchListener{
private Bitmap mBitmap;
Canvas mCanvas=new Canvas();
Path mPath=new Path();
Paint mBitmapPaint=new Paint(Paint.DITHER_FLAG);
Paint mPaint=new Paint();
Paint circlePaint=new Paint();
Path circlePath = new Path();
Context context;
#Override
protected 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);
mCanvas = new Canvas(mBitmap);
}
public BlackPixel(Context context) {
super(context);
setFocusable(true);
setFocusableInTouchMode(true);
this.setOnTouchListener(this);
}
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
canvas.drawBitmap( mBitmap, 0, 0, mBitmapPaint);
canvas.drawPath( mPath, mPaint );
canvas.drawPath( circlePath,circlePaint );
}
// #Override
public boolean onTouch(View v, MotionEvent event) {
float x=event.getX();
float y=event.getY();
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
touch_start(x,y);
invalidate();
return true;
case MotionEvent.ACTION_MOVE:
touch_move(x,y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up(x,y);
invalidate();
break;
}
return true;
}
private void touch_start(float x, float y)
{
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
}
private float mX,mY;
private static final float TOUCH_TOLERANCE = 4;
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;
}
}
private void touch_up(float x , float y)
{
mPath.lineTo(mX, mY);
// commit the path to our offscreen
mCanvas.drawPath(mPath, mPaint);
// kill this so we don't double draw
mPath.reset();
}
class Point
{
float x,y;
}
EDIT: this reflects changes you made in your code.
When you create mPaint, you're not setting its' style, which by default is FILL. Change it to STROKE. You can also set the stroke width. Do it in your constructor:
public BlackPixel(Context context) {
super(context);
setFocusable(true);
setFocusableInTouchMode(true);
this.setOnTouchListener(this);
//change paint style to STROKE
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(12);
}
Also, you can set the background color in onSizeChanged:
#Override
protected 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);
//set background color
mBitmap.eraseColor(0xFFAAAAAA);
mCanvas = new Canvas(mBitmap);
}
Check FingerSample in Android SDK samples folder.