简体   繁体   中英

How to draw a rounded corner rectangle progressively with canvas

I have a button which I want to draw a rounded corner rectangle around it progressively after I clicked it. I try to draw bezier curves in a canvas however I could not find the formula of a bezier curve that could paint a rounded corner rectangle. So I end up drawing four straight lines to create a rectangle without rounded corners. Below is the relative code:

public class CustomProgressBar extends View{

private Paint paint = new Paint();
public HomeFragment mHomeFragment;
private Context context;
private Path path;
int width = 178;
int height = 58;
int x1=0;
int y1=0;
int x2=width;
int y2=0;
int x3=width;
int y3=height;
int x4=0;
int y4=height;
int currentLine=0;
int stepLength = 8;

public CustomProgressBar(Context context) {
    super( context );

}

public CustomProgressBar(Context context, AttributeSet attrs) {

    super( context, attrs );
    this.context = context;
}

public CustomProgressBar(Context context, AttributeSet attrs, int defStyle) {

    super( context, attrs, defStyle );
}

public void init(HomeFragment homeFragment){
    this.mHomeFragment = homeFragment;
    paint.setStyle(Paint.Style.STROKE);
    paint.setStrokeWidth(6);
    paint.setColor(Color.rgb(203,156,76));
    setCoordinates();
}

public void setCoordinates(){
    new Thread(new Runnable() {
        @Override
        public void run() {
            while (true){
                switch (currentLine){
                    case 0:
                        if(x1<width) {
                            x1 += stepLength;
                        }else {
                            currentLine = 1;
                        }
                        break;
                    case 1:
                        if(y2<=height){
                            y2 += stepLength;
                        }else {
                            currentLine = 2;
                        }
                        break;
                    case 2:
                        if(x3>=0){
                            x3 -= stepLength;
                        }else {
                            currentLine = 3;
                        }
                        break;
                    case 3:
                        if(y4 >= 0){
                            y4 -= stepLength;
                        }else {
                            currentLine = 0;
                            x1 = 0;
                            y2 = 0;
                            x2 = width;
                            y2 = 0;
                            x3 = width;
                            y3 = height;
                            x4 = 0;
                            y4 = height;
                        }
                        break;
                }
                mHomeFragment.getActivity().runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        invalidate();
                    }
                });
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }
    }).start();

}


int max=100;
int progress=20;
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    switch (currentLine){
        case 0:
            canvas.drawLine(0, 0, x1, y1, paint);
            break;
        case 1:
            canvas.drawLine(0, 0, x1, y1, paint);
            canvas.drawLine(width, 0, x2, y2, paint);
            break;
        case 2:
            canvas.drawLine(0, 0, x1, y1, paint);
            canvas.drawLine(width, 0, x2, y2, paint);
            canvas.drawLine(width, height, x3, y3, paint);
            break;
        case 3:
            canvas.drawLine(0, 0, x1, y1, paint);
            canvas.drawLine(width, 0, x2, y2, paint);
            canvas.drawLine(width, height, x3, y3, paint);
            canvas.drawLine(0, height, x4, y4, paint);
            break;

    }
}
}

Does anyone know how to draw a rounded corner rectangle with a canvas? Any help is much appreciated!

您应该使用drawRoundRect()

canvas.drawRoundRect(rect, rx, ry, paint);

It seems that there is not much information about how to draw round rectangle in java on the internet. So I modified a js demo which introduced by @pskink into a java version. Below is the full code:

class DrawRoundRectangle extends View {
Paint paint;
int strokWidth = 6;
Path path;
// define the rectangle
int offsetX = 75;
int offsetY = 100;
int horizLineLength = 240;
int vertLineLength = 40;
int cornerRadius = 100;

// calc some lengths for use in percent complete
int cornerLength = (int) (2 * cornerRadius * Math.PI);
int totalLength = cornerLength * 4 + horizLineLength * 2 + vertLineLength * 2;
MainActivity ma;

// calc at what accumulated length each part of the rect starts
int startT = 0;
int startTR = horizLineLength;
int startR = startTR + cornerLength;
int startBR = (int) (startR + vertLineLength);
int startB = startBR + cornerLength;
int startBL = startB + horizLineLength;
int startL = startBL + cornerLength;
int startTL = startL + vertLineLength;

// percent complete
int percent = 100;
private int accumLength;
private double d1;
private double d2;
private double d3;
private double d4;
private double d5;
private double d6;
private double d7;
private double d8;
int x1;
int y1;
int x2;
int y2;
int x;
int y;
double start;
double end1;
double end2;
double end3;
double end4;
Canvas canvas;

public DrawRoundRectangle(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    paint = new Paint();
    paint.setStrokeWidth(strokWidth);
    paint.setColor(Color.rgb(203,156,76));
    path = new Path();
    Paint.Style style = paint.getStyle();
    paint.setStyle(style.STROKE);
}

float progress = 0;
float stepLength = 0.5f;

@Override
protected void onDraw(Canvas canvas) {
    //canvas.drawPath(segment, paint);
        this.canvas = canvas;

    drawPercentRect(progress);
    progress+=stepLength;
    if(progress >= 100){
        progress = 0;
        path.reset();
    }
}

// draw the radius rectangle
private void resetVars(){
    d1=0;
    d2=0;
    d3=0;
    d4=0;
    d5=0;
    d6=0;
    d7=0;
    d8=0;
    end1=0;
    end2=0;
    end3=0;
    end4=0;
}
private void drawPercentRect(float percent) {

    // percent expressed as a length-traveled-along-rect
    accumLength = (int) (percent / 100 * totalLength);

    // clear the canvas
    //ctx.clearRect(0, 0, canvas.width, canvas.height);

    // top line
    resetVars();
    d1 = accumLength - startT;
    d1 = Math.min(d1, horizLineLength);
    stepLength = 0.5f;
    if (d1 > 0) {
        x1 = offsetX + cornerRadius;
        y1 = offsetY;
        x2 = (int) (offsetX + cornerRadius + d1);
        y2 = offsetY;
        drawLine(x1, y1, x2, y2);
    }

    // top-right corner
    d2 = accumLength - startTR;
    d2 = Math.min(d2, cornerLength);
    if (d2 > 0) {
        x = offsetX + 50 + horizLineLength;
        y = offsetY;
        start =  270;
        end1 =  90*(d2/cornerLength);
        drawCorner(x, y, start, end1);
    }

    // right line
    d3 = accumLength - startR;
    d3 = Math.min(d3, vertLineLength);
    if (d3 > 0) {
        x1 = offsetX + cornerRadius + horizLineLength + cornerRadius/2;
        y1 = offsetY + cornerRadius/2;
        x2 = offsetX + cornerRadius + horizLineLength + cornerRadius/2;
        y2 = (int) (offsetY + cornerRadius/2 + d3);
        drawLine(x1, y1, x2, y2);
    }

    // bottom-right corner
    d4 = accumLength - startBR;
    d4 = Math.min(d4, cornerLength);
    if (d4 > 0) {
        x = offsetX  + horizLineLength+cornerRadius/2;
        y = offsetY  + vertLineLength;
        start = 0;
        //end = (int) ((d / cornerLength) * Math.PI / 2);
        end2 = 90*(d4/cornerLength);
        drawCorner(x, y, start, end2);
    }

    // bottom line
    d5 = accumLength - startB;
    d5 = Math.min(d5, horizLineLength);
    if (d5 > 0) {
        x1 = offsetX + cornerRadius + horizLineLength;
        y1 = offsetY + cornerRadius + vertLineLength;
        x2 = (int) (offsetX + cornerRadius + horizLineLength - d5);
        y2 = offsetY + cornerRadius + vertLineLength;
        drawLine(x1, y1, x2, y2);
    }

    // bottom-left corner
    d6 = accumLength - startBL;
    d6 = Math.min(d6, cornerLength);
    if (d6 > 0) {
        x = offsetX + cornerRadius/2;
        y = offsetY + vertLineLength;
        start = 90;
        end3 = 90*(d6/cornerLength);
        drawCorner(x, y, start, end3);
    }

    // left line
    d7 = accumLength - startL;
    d7 = Math.min(d7, vertLineLength);
    if (d7 > 0) {
        x1 = offsetX + cornerRadius/2;
        y1 = offsetY + cornerRadius/2 + vertLineLength;
        x2 = offsetX + cornerRadius/2;
        y2 = (int) (offsetY + cornerRadius/2 + vertLineLength - d7);
        drawLine(x1, y1, x2, y2);
    }

    // top-left corner
    d8 = accumLength - startTL;
    d8 = Math.min(d8, cornerLength);
    if (d8 > 0) {
        x = offsetX+cornerRadius/2;
        y = offsetY;
        start = 180;
        end4 = 90*(d8/cornerLength);
        drawCorner(x, y, start, end4);
    }

}

private void drawLine(int x1, int y1, int x2, int y2) {
    //ctx.beginPath();
    path.moveTo(x1, y1);
    path.lineTo(x2, y2);
    canvas.drawPath(path, paint);
    //ctx.stroke();
}

private void drawCorner(int x, int y, double start, double end) {
    if(end<90){
        progress+=4*stepLength;
    }
    path.arcTo(x, y, x + cornerRadius, y + cornerRadius, (float) start(float) end,true);
    canvas.drawPath(path, paint);
}

public void start(final MainActivity ma) {
    this.ma = ma;
    new Thread(new Runnable() {
        @Override
        public void run() {
            while (true) {
                ma.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        invalidate();
                    }
                });
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }
    }).start();

}
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM