2017-09-26 13 views
1

클릭 한 후 점진적으로 둥근 모서리 사각형을 그려야하는 버튼이 있습니다. 캔버스에 베 지어 커브를 그리려고하지만 둥근 모서리 사각형을 칠할 수있는 베 지어 커브의 수식을 찾을 수 없습니다. 그래서 저는 둥근 모서리가없는 직사각형을 만들기 위해 4 개의 직선을 그립니다. 아래는 상대 코드입니다.캔버스를 사용하여 점진적으로 둥근 모서리 사각형을 그리는 방법

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; 

    } 
} 
} 

누구나 캔버스로 둥근 모서리를 그리는 법을 아십니까? 어떤 도움을 많이 주시면 감사하겠습니다!

+0

이 https://stackoverflow.com/a/44987112/2252830 – pskink

답변

0

당신은()

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

볼 것은 drawRoundRect가 점진적으로 둥근 사각형을 그릴 수있는 방법이있다 : 아래의 전체 코드는? – user1870797

+0

나중에 다시 시도해 보겠습니다. 그것은 내가 찾고있는 것 같다. 하지만 베지에 곡선에 대해 많은 지식을 가지고 있지 않으며 짧은 순간에 그것을 익힐 수있을 것 같지 않습니다. 좋은 베 지어 곡선 튜토리얼을 주시겠습니까? 아니면 실용적인 예를 들어 주시겠습니까? – user1870797

+0

나는 그것을 조금 읽었다. 하지만 src.cubicTo 메소드의 개념을 이해하는 것은 혼란 스럽습니다. 나는 나중에 그것에 대해 더 많이 읽을 것이다. 감사! – user1870797

0

것은 drawRoundRect를 사용해야은 인터넷에서 자바 둥근 사각형을 그릴하는 방법에 대한 많은 정보가없는 것 같다. 그래서 @pskink가 자바 버전으로 도입 한 js 데모를 수정했습니다.

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

} 
} 
+0

은 [this] (https://pastebin.com/raw/qtjVq2jY)와 비교할 수 있습니다. 예, 둥근 사각형을 그리는 방법에 대한 충분한 정보가 있습니다. 모두 'android.graphics.Canvas' 또는/and'android.graphics.Path' 문서를 읽는 것이 필요합니다. – pskink

+0

@pskink이 솔루션은 놀랍도록 짧고 깨끗합니다. 나는 나중에 그것을 시도 할 것이다. – user1870797

+0

다음 번에 공식 문서를 읽으십시오. (이것은 내가 이미 3 번 말했던 것입니다) – pskink