1

I'm trying to draw a warped rectangle using Canvas. I've tried using Path to draw the straight line and then arcTo(), but I don't know which values should I use. How do I draw a shape similat to the one in the image?

enter image description here

EDIT: This code doesn't work, it draws a straight line.

        Path path = new Path();
        path.moveTo(width/2-10, (height/2)+130);
        path.lineTo(width/2-12, (height/2)+170);

        float x1 = width/2-12; //228
        float y1 = height/2+170; //570
        float x3 = width/2-70; //170
        float y3 = height/2+140; //540
        float x2 = (x3+x1)/2; //199
        float y2 = (y3+y1)/2; //555

        path.quadTo(x1, y1, x2, y2);
        Paint paint = new Paint()
        {
            {
                setStyle(Paint.Style.STROKE);
                setColor(Color.YELLOW);
                setStrokeCap(Paint.Cap.ROUND);
                setStrokeWidth(3.0f);
                setAntiAlias(true);
            }
        };
        mCanvas.drawPath(path, paint);
domen
  • 1,239
  • 3
  • 15
  • 26

1 Answers1

1

Here's an interesting solution I found here:

You can use Path.quadTo() or Path.cubicTo() for that. Examples can be found in the SDK Examples (FingerPaint). In your case you would simply need to calculate the middle point and pass then your three points to quadTo()..

Some code for you:

  • (x1,y1) and (x3,y3) are your starting and ending points respectively.
  • create the paint object only once (e.g. in your constructor)

    Paint paint = new Paint() {
        {
            setStyle(Paint.Style.STROKE);
            setStrokeCap(Paint.Cap.ROUND);
            setStrokeWidth(3.0f);
            setAntiAlias(true);
        }
    };
    final Path path = new Path();
    path.moveTo(x1, y1);
    
    final float x2 = (x3 + x1) / 2;
    final float y2 = (y3 + y1) / 2;
            path.quadTo(x2, y2, x3, y3);
    canvas.drawPath(path, paint);
    

From the documentation here:

public void cubicTo (float x1, float y1, float x2, float y2, float x3, float y3)

Add a cubic bezier from the last point, approaching control points (x1,y1) and (x2,y2), and ending at (x3,y3). If no moveTo() call has been made for this contour, the first point is automatically set to (0,0).

Parameters x1 The x-coordinate of the 1st control point on a cubic curve

y1 The y-coordinate of the 1st control point on a cubic curve

x2 The x-coordinate of the 2nd control point on a cubic curve

y2 The y-coordinate of the 2nd control point on a cubic curve

x3 The x-coordinate of the end point on a cubic curve

y3 The y-coordinate of the end point on a cubic curve

EDIT: In your case I think you should change the code to:

final Path path = new Path();
path.moveTo(width/2-12, (height/2+170);

float x1 = width/2-12; //228
float y1 = height/2+170; //570
float x3 = width/2-70; //170
float y3 = height/2+140; //540
float x2 = (x3+x1)/2 + 14.5; //213.5
float y2 = (y3+y1)/2 + 7.5; //562.5

path.quadTo(x2, y2, x3, y3);
Paint paint = new Paint()
{
    {
        setStyle(Paint.Style.STROKE);
        setColor(Color.YELLOW);
        setStrokeCap(Paint.Cap.ROUND);
        setStrokeWidth(3.0f);
        setAntiAlias(true);
    }
};
mCanvas.drawPath(path, paint);
Community
  • 1
  • 1
g00dy
  • 6,752
  • 2
  • 30
  • 43
  • I've tried using both quadTo() and cubicTo(), but it just creates a straight line, with no curvature. – domen Jul 15 '13 at 10:50
  • Paste here the coordinates you're passing to `quadTo()` function and how do you obtain them. – g00dy Jul 15 '13 at 11:06
  • Updated the original post. – domen Jul 15 '13 at 11:13
  • I think that the `lineTo()` is drawing the line. – g00dy Jul 15 '13 at 11:29
  • That draws the first straight line and then there should be an arc, but it's just another straight line. – domen Jul 15 '13 at 12:35
  • I'm voting this question up, but if the EDIT I made to the post isn't working then I shall remove the answer from there. I really don't understand why it shouldn't work .. – g00dy Jul 15 '13 at 12:37
  • I've tried your code in the EDIT, but it still draws a straight line. – domen Jul 15 '13 at 12:50
  • If the middle point is on the straight line between the starting point (x1, y1) and the end point (x3, y3), then the curve will not be visible, but it will be there. Try changing the values for the pair (x2,y2) and see if you can move the middle point with that. – g00dy Jul 15 '13 at 13:16
  • And as I see this is the case, so change x2 and y2 to : `float x2 = (x3+x1)/2 + 14.5; //213.5` and `float y2 = (y3+y1)/2 + 7.5; //562.5`. Hope it works now. – g00dy Jul 15 '13 at 13:33
  • Phew, I almost threw myself off the window. Sometimes those small details, which are left over turn out to be the most important ones. – g00dy Jul 15 '13 at 14:32