我有以下自定义视图:
我使用Canvas的drawArc()
方法实现了这个视图。然而,使用这个方法时,我无法限制弧形的内部半径。
我想要的是像这样的效果:
只剩下一个外环。
我需要一个可以设置弧形内部半径的drawArc()
函数。 有人有什么想法吗?
(顺便说一下,覆盖内部区域是不起作用的,因为它需要是透明的。在绘制红色和蓝色圆锥之后,使用Color.TRANSPARENT
绘制内部圆形并不能清除旧颜色。 它只是放置另一层在上面,这一层是透明的,通过它我仍然可以看到红色和蓝色)
我有以下自定义视图:
我使用Canvas的drawArc()
方法实现了这个视图。然而,使用这个方法时,我无法限制弧形的内部半径。
我想要的是像这样的效果:
只剩下一个外环。
我需要一个可以设置弧形内部半径的drawArc()
函数。 有人有什么想法吗?
(顺便说一下,覆盖内部区域是不起作用的,因为它需要是透明的。在绘制红色和蓝色圆锥之后,使用Color.TRANSPARENT
绘制内部圆形并不能清除旧颜色。 它只是放置另一层在上面,这一层是透明的,通过它我仍然可以看到红色和蓝色)
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、厚度为20px的弧形)。
希望对您有所帮助!
paint.setStrokeCap(Paint.Cap.BUTT);
而不是 paint.setStrokeCap(Paint.Cap.ROUND);
,你将得到与问题所要求的完全相同的结果。 - PhoneixScanvas.drawArc(rect,0,360,false,paint);
替代 -90。 - Gerard您可以使用名为“Clear”的PorterDuff xfermode在内部区域上绘制,这将擦除像素。
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 ±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);
}
}
通过复制rInn
和rOut
来扩展为椭圆弧,分别用于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);
segmentPath.*To()
调用拆分成多个Path
,并使用所选的描边颜色分别绘制每个Path
。你可以使用2个路径来实现你所描述的效果:moveTo,lineTo,moveTo,lineTo
和moveTo,arcTo,moveTo,arcTo
。你仍然需要保留当前的路径以便填充。 - TWiStErRoblineTo
。对于第二个 arcTo()
,在最后一个参数中添加 false
;这将从第一个弧的末端绘制一条线到第二个弧的开头。然后关闭路径(close()
)。 - John Perry int sweepAngle sweepAngle = (360/7)%360;
int startAngle = -90;
int x = getWidth()/2;
int y = getHeight()/2;
int radius;
radius = getWidth()/2-50;
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(50);
paint.setColor(Color.WHITE);
paint.setColor(Color.parseColor("#CD5C5C"));
mBarPaintFill.setAntiAlias(true);
canvas.drawCircle(x , y , radius, paint);
paint.setColor(Color.BLUE);
for (int i = 1 ; i<=5 ; i++){
canvas.drawArc(x-radius,y-radius,x+radius,y+radius,startAngle,sweepAngle,false,paint);
startAngle = (startAngle + sweepAngle+20)%360;
}
<?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>