Daw line between 2 points

5.5k views Asked by At

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>
2

There are 2 answers

2
Patel Hiren On
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);

2
Muhammad Usman On

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);