2010-10-06 5 views
31

У меня есть следующий вид: пользовательскогоAndroid: ищу метод drawArc() с внутренним и внешним радиусом

alt text

Это Я достигнутый с помощью метода drawArc() холста. Однако с помощью этого метода drawArc() я не могу ограничить внутренний радиус дуги.

То, что я хотел бы иметь что-то вроде этого:

alt text

где есть только внешнее кольцо влево.

Мне нужна функция drawArc(), где я могу установить внутренний радиус дуги. Кто-нибудь знает, как это сделать?

(BTW, перекрашивание внутренней области не работает, потому что оно должно быть прозрачным. Окраска внутреннего круга с помощью Color.TRANSPARENT после окраски красных и синих конусов не удаляет старый цвет. верхняя часть, прозрачная и через которую я все еще вижу красный и синий)

+7

Вы можете разместить ваш последний код получил свое окончательное требование? Спасибо – anddev

+0

Кто-нибудь знает, как сделать гладкие края углов встречи, так как в моем случае, когда я делаю кольцо с 4-5 равным распределением и разными цветами, я вижу фон на краях. –

ответ

28

Вы можете рисовать по внутренней области с помощью протокола PorterDuff xfermode под названием «Очистить». Это приведет к стиранию пикселей.

+1

Это возможное решение. Но что делать по этому делу, что в внутреннем круге уже есть что-то, что я не хочу перекрасить, и ни я не хочу стереть пиксели и перерисовать его? – znq

+1

Нарисуйте круг в заставке ARCH8888 растрового изображения, сделайте там ясное, затем нарисуйте растровое изображение на вашем холсте. И таким образом вам также не нужно каждый раз перерисовывать круг. –

+0

Итак, посмотрев, как на самом деле это сделать, я немного потерялся: это растровое изображение ARGB8888 «нормальное» Bitmap http://goo.gl/ygTn - и как мне получить те же функции рисования, что и я с холстом? – znq

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 и 20px толщиной).

Надеюсь, это поможет!

+0

Работает как очарование! Иногда я забываю вычесть удар из контейнера, и я получаю обрезанный круг. Благодарю. – Tom

+3

И если вы используете 'paint.setStrokeCap ​​(Paint.Cap.BUTT);' вместо 'paint.setStrokeCap ​​(Paint.Cap.ROUND);' вы получаете именно то, чего хочет этот вопрос. – PhoneixS

+5

Я думаю, что вы можете безопасно использовать 'canvas.drawArc (rect, 0,360, false, paint);' вместо -90 – Gerard

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

Может быть расширен до овальной дуги, дублируя rInn и rOut для й и у.

Также не было частью вопроса, но нарисовать текст в середине сегмента:

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

+0

@Snake, вам придется разделить 'segmentPath. * To()' вызывает на несколько 'Path' и рисует каждый отдельно с вашими цветами штриховки. Вы можете делать то, что вы описываете, с двумя путями: 'moveTo, lineTo, moveTo, lineTo' и' moveTo, arcTo, moveTo, arcTo'. Вам все равно придется держать текущий, чтобы что-то заполнить. – TWiStErRob

+0

Я «думаю», я смутно это понял. Поскольку я все еще нуждаюсь в вашей помощи, я создал еще один вопрос, как вы предложили. Ждем вашей помощи. Вот ссылка http://stackoverflow.com/questions/27850634/change-the-following-code-to-include-different-colors-for-different-strokes – Snake

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> 

 Смежные вопросы

  • Нет связанных вопросов^_^