2010-10-06 57 views
31

一个drawArc()方法我有以下定制视图:机器人:寻找与内外半径

alt text

这我已通过使用画布drawArc()方法来实现。然而,用这种方法我不能限制弧的内半径。

我想什么有是这样的:

alt text

那里只有外圈离开。

我需要的是一个drawArc()函数,我可以设置弧的内半径。任何人有一个想法如何做到这一点?

(顺便说一下,覆盖内部区域不起作用,因为它需要透明。在绘制红色和蓝色圆锥体后用Color.TRANSPARENT绘制内部圆圈并不会除去旧颜色,顶部,这是透明的,通过它我仍然可以看到红色和蓝色)

+7

您可以发布你的最新代码在得到你的最终要求之后?谢谢 – anddev 2012-02-09 06:27:40

+0

是否有人知道如何使会议角度平滑的边缘,在我的情况下,当我制作4-5等分布和不同颜色的环时,我可以在边缘看到背景 – 2014-10-14 09:29:32

回答

28

您可以使用名为“Clear”的PorterDuff xfermode在内部区域上绘画。这会擦除像素。

+1

这是一个可能的解决方案。但是对于这种情况该怎么办呢,内圈已经有了一些东西,我不希望覆盖它,也不想擦除像素并重新绘制它们? – znq 2010-10-06 17:57:14

+1

在离屏ARGB8888位图上绘制圆,在那里清除,然后将位图绘制到画布上。这样你就不必每次都重绘这个圈子。 – 2010-10-07 02:58:08

+0

因此,在研究如何真正做到这一点之后,我有点迷失了:是一个ARGB8888位图是一个“普通”位图http://goo.gl/ygTn--以及如何获得与我一样的绘图功能与画布? – znq 2010-10-07 10:52:12

67

你可以这样做:

Paint paint = new Paint(); 
    final RectF rect = new RectF(); 
    //Example values 
    rect.set(mWidth/2- mRadius, mHeight/2 - mRadius, mWidth/2 + mRadius, mHeight/2 + mRadius); 
    paint.setColor(Color.GREEN); 
    paint.setStrokeWidth(20); 
    paint.setAntiAlias(true); 
    paint.setStrokeCap(Paint.Cap.ROUND); 
    paint.setStyle(Paint.Style.STROKE); 
    canvas.drawArc(rect, -90, 360, false, paint); 

的关键是paint.setStyle(Paint.Style.STROKE);,它裁剪弧与您在setStrokeWidth定义行程中心(在示例绘制mRadius和20像素厚的半径的圆弧)。

希望它有帮助!

+0

工程就像一个魅力!有时我会忘记从容器中减去笔画,并得到一个裁剪的圆圈。谢谢。 – Tom 2012-06-12 14:43:25

+3

如果你使用'paint.setStrokeCap(Paint.Cap.BUTT);'而不是'paint.setStrokeCap(Paint.Cap.ROUND);'你得到了正确的问题。 – PhoneixS 2013-07-02 19:22:15

+5

我认为你可以安全地使用'canvas.drawArc(rect,0,360,false,paint);'而不是-90 – Gerard 2013-10-30 21:12:46

16
private static final float CIRCLE_LIMIT = 359.9999f; 
/** 
* Draws a thick arc between the defined angles, see {@link Canvas#drawArc} for more. 
* This method is equivalent to 
* <pre><code> 
* float rMid = (rInn + rOut)/2; 
* paint.setStyle(Style.STROKE); // there's nothing to fill 
* paint.setStrokeWidth(rOut - rInn); // thickness 
* canvas.drawArc(new RectF(cx - rMid, cy - rMid, cx + rMid, cy + rMid), startAngle, sweepAngle, false, paint); 
* </code></pre> 
* but supports different fill and stroke paints. 
* 
* @param canvas 
* @param cx horizontal middle point of the oval 
* @param cy vertical middle point of the oval 
* @param rInn inner radius of the arc segment 
* @param rOut outer radius of the arc segment 
* @param startAngle see {@link Canvas#drawArc} 
* @param sweepAngle see {@link Canvas#drawArc}, capped at &plusmn;360 
* @param fill filling paint, can be <code>null</code> 
* @param stroke stroke paint, can be <code>null</code> 
* @see Canvas#drawArc 
*/ 
public static void drawArcSegment(Canvas canvas, float cx, float cy, float rInn, float rOut, float startAngle, 
     float sweepAngle, Paint fill, Paint stroke) { 
    if (sweepAngle > CIRCLE_LIMIT) { 
     sweepAngle = CIRCLE_LIMIT; 
    } 
    if (sweepAngle < -CIRCLE_LIMIT) { 
     sweepAngle = -CIRCLE_LIMIT; 
    } 

    RectF outerRect = new RectF(cx - rOut, cy - rOut, cx + rOut, cy + rOut); 
    RectF innerRect = new RectF(cx - rInn, cy - rInn, cx + rInn, cy + rInn); 

    Path segmentPath = new Path(); 
    double start = toRadians(startAngle); 
    segmentPath.moveTo((float)(cx + rInn * cos(start)), (float)(cy + rInn * sin(start))); 
    segmentPath.lineTo((float)(cx + rOut * cos(start)), (float)(cy + rOut * sin(start))); 
    segmentPath.arcTo(outerRect, startAngle, sweepAngle); 
    double end = toRadians(startAngle + sweepAngle); 
    segmentPath.lineTo((float)(cx + rInn * cos(end)), (float)(cy + rInn * sin(end))); 
    segmentPath.arcTo(innerRect, startAngle + sweepAngle, -sweepAngle); 
    if (fill != null) { 
     canvas.drawPath(segmentPath, fill); 
    } 
    if (stroke != null) { 
     canvas.drawPath(segmentPath, stroke); 
    } 
} 

可以通过复制rInnrOut为x和y方向扩展到椭圆弧。

也没问题的一部分,但在段的中间画一个文本:

textPaint.setTextAlign(Align.CENTER); 
Path midway = new Path(); 
float r = (rIn + rOut)/2; 
RectF segment = new RectF(cx - r, cy - r, cx + r, cy + r); 
midway.addArc(segment, startAngle, sweepAngle); 
canvas.drawTextOnPath("label", midway, 0, 0, textPaint); 
+0

这段代码太神奇了!然而,我有一个问题,是否有办法让圆圈之间的线条具有与圆周边颜色不同的颜色? – Snake 2015-01-08 19:39:32

+0

@Snake,你必须将'segmentPath。* To()'调用拆分成多个'Path's,并且用你选择的笔画颜色分别绘制。你可以用2条路径来描述你所描述的:moveTo,lineTo,moveTo,lineTo和moveTo,arcTo,moveTo,arcTo。你仍然需要保留当前的东西来填充。 – TWiStErRob 2015-01-08 22:03:15

+0

我“想”我隐约明白它。由于我仍然需要你的帮助,所以我建立了另一个问题。期待您的帮助。这是链接http://stackoverflow.com/questions/27850634/change-the-following-code-to-include-different-colors-for-different-strokes – Snake 2015-01-08 22:25:34

2

你可以尝试以下ShapeDrawable

<?xml version="1.0" encoding="utf-8"?> 
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" > 
<item> 
    <shape android:shape="oval" > 
     <size 
      android:height="56dp" 
      android:width="56dp" /> 

     <stroke 
      android:width="10dp" 
      android:color="#0000ff" /> 
    </shape> 
</item> 
<item> 
    <shape android:shape="oval" > 
     <size 
      android:height="24dp" 
      android:width="25dp" /> 

     <stroke 
      android:dashGap="10dp" 
      android:dashWidth="10dp" 
      android:width="10dp" 
      android:color="#FF0000" /> 
    </shape> 
</item>