Related
I am building an app where a user can draw lines in a custom canvas with a finger (multiple fragments have a canvas and this works) using the Path class.
I also managed to use SharedPreferences to save and load the drawn lines but when loaded the lines start from the top left (i.e (0, 0)) and the shape has changed to lines with a slight curve at the start (I say start because I found that the line ends from where the touch started).
The start points are kept in Path but from what I can see there are no endpoints kept. Is there any way I can get the endpoints?
I have previously tried passing the required variables to another ArrayList that uses another constructor with the endpoints (found with a method used for when the finger stops touching the screen) but the drawings no longer showed on the canvas unlike before.
Edit
I have changed to finding multiple points as I believe that getting the endpoint won't be enough and have altered the shown code to show my attempt with getPosTan but no drawings get shown as the elements in testing are null for some reason, so it won't go in the else.
Update
I found that pathMeasure.getLength() produces 0.0 so it isn't going into the while and therefore resulting in null elements but I don't know why it's producing 0.0 as somePath isn't null
PaintView.java
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.EmbossMaskFilter;
import android.graphics.MaskFilter;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import java.util.ArrayList;
public class PaintView extends View {
public static int BRUSH_SIZE = 10;
public static final int DEFAULT_COLOR = Color.WHITE;
public static int DEFAULT_BG_COLOR = Color.GRAY;
private static final float TOUCH_TOLERANCE = 4;
private float mX, mY;
private Path mPath;
private Paint mPaint;
private static 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;
public 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 ArrayList getPaths() {
return paths;
}
public ArrayList setPaths(ArrayList<FingerPath> list) {
return this.paths = list;
}
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);
loadDrawing(mCanvas);
currentColor = DEFAULT_COLOR;
strokeWidth = BRUSH_SIZE;
}
public void normal() {
emboss = false;
blur = false;
}
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, x, y);
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;
}
private FloatPoint[] getPoint(Path somePath, float x, float y){
FloatPoint[] pointArray = new FloatPoint[20];
PathMeasure pathMeasure = new PathMeasure(somePath, false);
float length = pathMeasure.getLength();
float distance = 0f;
float speed = length / 20;
int counter = 0;
float[] aCoordinates = {x, y};
while ((distance < length) && (counter < 20)) {
pathMeasure.getPosTan(distance, aCoordinates, null);
pointArray[counter] = new FloatPoint(aCoordinates[0],
aCoordinates[1]);
counter++;
distance = distance + speed;
}
return pointArray;
}
public void loadDrawing(Canvas canvas) {
if (mCanvas != null) {
currentColor = DEFAULT_COLOR;
strokeWidth = BRUSH_SIZE;
if (! paths.isEmpty()) {
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);
FloatPoint[] testing = getPoint(fp.path, fp.x, fp.y);
//need to figure out how to for loop testing
float sectionTestX = 0.0f;
float sectionTestY = 0.0f;
for (FloatPoint testingPoint : testing) {
if (sectionTestX == 0.0f && sectionTestY == 0.0f) {
sectionTestX = testingPoint.getX();
sectionTestY = testingPoint.getY();
continue;
} else {
fp.path.quadTo(sectionTestX, sectionTestY,
testingPoint.getX(), testingPoint.getY());
sectionTestX = testingPoint.getX();
sectionTestY = testingPoint.getY();
}
}
/*xTest = fp.x;
yTest = fp.y;*/
}
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.restore();
}
}
}
}
FloatPoint.java
public class FloatPoint {
static float x, y;
public FloatPoint(float x, float y) {
this.x = x;
this.y = y;
}
public static float getX() {
return x;
}
public static float getY() {
return y;
}
}
I am able to pinch zoom in/out (though its not perfect yet) i want to use 2 fingers to drag since single drag is for drawing.
is this where the ACTION_POINTER_DOWN is required?
please help me how i can have the paint app drag with 2 fingers?
Below is the code
Thank you!
public class paintView extends View {
private static final int INVALID_POINTER_ID = -1;
private float mPosX;
private float mPosY;
private int mActivePointerId = INVALID_POINTER_ID;
private final ScaleGestureDetector mScaleDetector;
private float mScaleFactor = 1.f;
Paint paint;
Path path;
public paintView(Context context) {
super(context, null, 0);
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
paint = new Paint();
path = new Path();
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(8f);
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
// Let the ScaleGestureDetector inspect all events.
mScaleDetector.onTouchEvent(ev);
final int action = ev.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
final float x = ev.getX();
final float y = ev.getY();
path.moveTo(x,y);
return true;
}
case MotionEvent.ACTION_MOVE: {
float x = ev.getX();
float y = ev.getY();
path.lineTo(x,y);
break;
}
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
}
invalidate();
return true;
}
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
// for moving around
// 2 finger drag 할때 필요할듯
canvas.translate(mPosX, mPosY);
// for zoom
canvas.scale(mScaleFactor, mScaleFactor);
//mImage.draw(canvas);
canvas.drawPath(path, paint);
//canvas.restore();
}
// zoom in gesture
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
#Override
public boolean onScale(ScaleGestureDetector detector) {
final float scale = detector.getScaleFactor();
mScaleFactor = Math.max(.5f, Math.min(mScaleFactor * scale, 3.0f));
if (mScaleFactor < 5f) {
// 1 Grabbing
final float centerX = detector.getFocusX();
final float centerY = detector.getFocusY();
// 2 Calculating difference
float diffX = centerX - mPosX;
float diffY = centerY - mPosY;
// 3 Scaling difference
diffX = diffX * scale - diffX;
diffY = diffY * scale - diffY;
// 4 Updating image origin
mPosX -= diffX;
mPosY -= diffY;
}
invalidate();
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;
}
}
I am trying to draw a line between 2 points. I can draw a line between 2 points like: A to B to C. But I want to draw lines between them like A to C or C to A.
Also I wanted to draw those lines on a image background. I have a background there, but when i draw a line with background my app is lagging.
Here's the code:
package com.example.grzegorz.kropy;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.drawable.*;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.graphics.BitmapFactory;
import java.util.ArrayList;
import java.util.List;
public class PaintView extends View {
private Bitmap mBitmap;
private Canvas mCanvas; // holds the "draw" calls
private Path mPath; //Create an empty path
private Paint mPaint; // the style and color information about how to draw geometries, text and bitmaps.
private static final int TOUCH_TOLERANCE_DP = 24;
private static final int BACKGROUND =0xFFCC00 ;
private List<Point> mPoints = new ArrayList<Point>();
private int mLastPointIndex = 0;
private int mTouchTolerance;
private boolean isPathStarted = false;
public PaintView(Context context) {
super(context);
mCanvas = new Canvas();
mPath = new Path();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(12);
mTouchTolerance = dp2px(TOUCH_TOLERANCE_DP);
// TODO just test points
Point p1 = new Point(20, 20);
Point p2 = new Point(100, 100);
Point p3 = new Point(200, 250);
Point p4 = new Point(280, 400);
Point p5 = new Point(350, 600);
Point p6 = new Point(400, 500);
Point p7 = new Point(450, 500);
mPoints.add(p1);
mPoints.add(p2);
mPoints.add(p3);
mPoints.add(p4);
mPoints.add(p5);
mPoints.add(p6);
mPoints.add(p7);
}
public PaintView(Context context, AttributeSet attrs) {
super(context, attrs);
mBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.polacz);
mCanvas = new Canvas();
mPath = new Path();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(12);
mTouchTolerance = dp2px(TOUCH_TOLERANCE_DP);
// TODO just test points
Point p1 = new Point(20, 20);
Point p2 = new Point(100, 100);
Point p3 = new Point(200, 250);
Point p4 = new Point(280, 400);
Point p5 = new Point(350, 600);
Point p6 = new Point(400, 500);
Point p7 = new Point(450, 500);
mPoints.add(p1);
mPoints.add(p2);
mPoints.add(p3);
mPoints.add(p4);
mPoints.add(p5);
mPoints.add(p6);
mPoints.add(p7);
}
public PaintView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
mCanvas = new Canvas();
mPath = new Path();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(12);
mTouchTolerance = dp2px(TOUCH_TOLERANCE_DP);
}
#Override
protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) {
super.onSizeChanged(width, height, oldWidth, oldHeight);
clear();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//canvas.drawColor(BACKGROUND);
Drawable d = getResources().getDrawable(R.drawable.polacz);
d.setBounds(canvas.getClipBounds());
d.draw(canvas);
// mCustomImage.setBounds(canvas.getClipBounds());
// mCustomImage.draw(canvas);
canvas.drawBitmap(mBitmap, 0, 0, null);
// canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.polacz1), 0, 0, null);
canvas.drawPath(mPath, mPaint);
// TODO remove if you dont want points to be drawn
for (Point point : mPoints) {
canvas.drawPoint(point.x, point.y, 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(x, y);
invalidate();
break;
}
return true;
}
private void touch_start(float x, float y) {
if (checkPoint(x, y, mLastPointIndex)) {
mPath.reset();
// user starts from given point so path can beis started
isPathStarted = true;
} else {
// user starts move from point which doen's belongs to mPinst list
isPathStarted = false;
}
}
private void touch_move(float x, float y) {
// draw line with finger move
if (isPathStarted) {
mPath.reset();
Point p = mPoints.get(mLastPointIndex);
mPath.moveTo(p.x, p.y);
if (checkPoint(x, y, mLastPointIndex + 1)) {
p = mPoints.get(mLastPointIndex + 1);
mPath.lineTo(p.x, p.y);
mCanvas.drawPath(mPath, mPaint);
mPath.reset();
++mLastPointIndex;
} else {
mPath.lineTo(x, y);
}
}
}
/**
* Draws line.
*/
private void touch_up(float x, float y) {
mPath.reset();
if (checkPoint(x, y, mLastPointIndex + 1) && isPathStarted) {
// move finished at valid point so draw whole line
// start point
Point p = mPoints.get(mLastPointIndex);
mPath.moveTo(p.x, p.y);
// end point
p = mPoints.get(mLastPointIndex + 1);
mPath.lineTo(p.x, p.y);
mCanvas.drawPath(mPath, mPaint);
mPath.reset();
// increment point index
++mLastPointIndex;
isPathStarted = false;
}
}
/**
* Sets paint
*
* #param paint
*/
public void setPaint(Paint paint) {
this.mPaint = paint;
}
/**
* Returns image as bitmap
*
* #return
*/
public Bitmap getBitmap() {
return mBitmap;
}
/**
* Clears canvas
*/
public void clear() {
mBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
mBitmap.eraseColor(BACKGROUND);
mCanvas.setBitmap(mBitmap);
invalidate();
}
/**
* Checks if user touch point with some tolerance
*/
private boolean checkPoint(float x, float y, int pointIndex) {
if (pointIndex == mPoints.size()) {
// out of bounds
return false;
}
Point point = mPoints.get(pointIndex);
//EDIT changed point.y to poin.x in the first if statement
if (x > (point.x - mTouchTolerance) && x < (point.x + mTouchTolerance)) {
if (y > (point.y - mTouchTolerance) && y < (point.y + mTouchTolerance)) {
return true;
}
}
return false;
}
public List<Point> getPoints() {
return mPoints;
}
public void setPoints(List<Point> points) {
this.mPoints = points;
}
private int dp2px(int dp) {
Resources r = getContext().getResources();
float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics());
return (int) px;
}
}
XML:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:focusableInTouchMode="false">
<com.example.grzegorz.kropy.PaintView
android:layout_width="670dp"
android:layout_height="820dp"
/>
<!--<Button-->
<!--android:layout_width="wrap_content"-->
<!--android:layout_height="wrap_content"-->
<!--android:text="graj"-->
<!--android:id="#+id/button"-->
<!--android:layout_alignParentTop="true"-->
<!--android:layout_alignParentLeft="true"-->
<!--android:onClick="gra"-->
<!--android:layout_alignParentStart="true" />-->
</RelativeLayout>
Try solution works for me
public class DrawView extends View {
Paint paint = new Paint();
View startView1;
View endView1;
int myToken;
float sX,sY,eX,eY;
public DrawView(Context context,View startView ,View endView) {
super(context);
paint.reset();
myToken=token;
paint.setStrokeWidth(3);
this.startView1 = startView;
this.endView1 = endView;
}
public void onDraw(Canvas canvas) {
paint.setColor(Color.GREEN);
canvas.drawLine(startView1.getX()+startView1.getWidth() / 2.F, startView1.getY()+startView1.getHeight()/ 2.F, endView1.getX()+endView1.getWidth() / 2.F, endView1.getY()+endView1.getHeight() / 2.F, paint);
}
}
and call this DrawView class as :
Button btn1=(Button) findViewById(id1);
Button btn2=(Button) findViewById(id2);
DrawView drawView = new DrawView(RoasterScreen.this,btn1,btn2);
rootLayout.addView(drawView);
public class DrawingPanel extends View implements OnTouchListener {
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;
private int color;
public int SSL = Color.WHITE;
private int x, y;
private int strockWidth = 3;
private String textToDraw = null;
public static boolean isTextModeOn = false;
//public static boolean flag = true;
//public static int angle = 0;
public DrawingPanel(Context context, int color, Bitmap bitmap) {
super(context);
this.color = color;
System.out.println("---> Drawing pannel Construction <--- ");
setFocusable(true);
setFocusableInTouchMode(true);
this.setOnTouchListener(this);
mBitmap = bitmap;
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.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(strockWidth);
mPaint.setTextSize(30);
mPath = new Path();
paths.add(new PathPoints(mPath, color,strockWidth, false));
mCanvas = new Canvas();
}
public void colorChanged(int color) {
this.color = color;
mPaint.setColor(color);
//invalidate();
}
public void changeWidthOfStrock(int strockWidth) {
this.strockWidth = strockWidth;
mPaint.setStrokeWidth(strockWidth);
//invalidate();
}
#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("Bitmap");
System.out.println("mBitmap"+mBitmap);
if(mBitmap != null) {
float xscale = (float) w / (float) mBitmap.getWidth();
float yscale = (float) h / (float) mBitmap.getHeight();
if (xscale > yscale) // make sure both dimensions fit (use the
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());
mPaint.setStrokeWidth(p.getStrockWidth());
if (p.isTextToDraw()) {
//canvas.drawText(p.textToDraw, p.x, p.y, mPaint);
} else {
canvas.drawPath(p.getPath(), mPaint);
}
}
mPaint.setColor(SSL);
mPaint.setStrokeWidth(strockWidth);
canvas.drawPath(mPath, mPaint);
}
private float mX, mY;
private static final float TOUCH_TOLERANCE = 0;
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);
// 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, SSL,strockWidth ,false));
mPath = new Path();
}
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
}
class PathPoints {
private Path path;
// private Paint mPaint;
private int color;
private int strockW;
private String textToDraw;
private boolean isTextToDraw;
private int x, y;
public PathPoints(Path path, int color,int strockWidth ,boolean isTextToDraw) {
this.path = path;
this.color = color;
this.strockW = strockWidth;
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;
}
/*
* private Paint getPaint() { mPaint = new Paint();
* mPaint.setAntiAlias(true); mPaint.setColor(color);
* mPaint.setStyle(Paint.Style.STROKE);
* mPaint.setStrokeJoin(Paint.Join.ROUND);
* mPaint.setStrokeCap(Paint.Cap.ROUND); mPaint.setStrokeWidth(6);
* return mPaint; }
*/
public int getColor() {
return color;
}
public void setColor(int color) {
this.color = color;
}
public int getStrockWidth() {
return strockW;
}
public void setStrokWidth(int color) {
this.strockW = 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;
}
}
}
Add this view into your layout
DrawingPanel drawingPanel = new DrawingPanel(getApplicationContext(), color, bitmap);
rl_layout.addView(drawingPanel);