Android: ищем метод drawArc () с внутренним и внешним радиусом

У меня есть следующий пользовательский вид:

Этого я достиг, используя CanvasdrawArc() метод. Однако с этимdrawArc() Метод я не могу ограничить внутренний радиус дуги.

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

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

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

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

 anddev09 февр. 2012 г., 07:27
Можете ли вы опубликовать свой последний код после получения окончательного требования? Спасибо
 Akhil Dad14 окт. 2014 г., 11:29
Кто-нибудь знает, как сделать ровные края встречных углов, как в моем случае, когда я делаю кольцо с 4-5 равным распределением и разными цветами, я вижу фон по краям

Ответы на вопрос(5)

Вы можете сделать это:

    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 пикселей).

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

 Gerard30 окт. 2013 г., 22:12
Я думаю, что вы можете безопасно использоватьcanvas.drawArc(rect,0,360,false,paint); вместо -90
 user186502731 мар. 2017 г., 20:47
это должен быть правильный ответ!
 Snake08 янв. 2015 г., 17:44
Можете ли вы установить градиент цвета (например, шейдер) для этого?
 Tom12 июн. 2012 г., 16:43
Работает как шарм! Иногда я забываю вычесть удар из контейнера и получаю обрезанный круг. Благодарю.
 Vitor Hugo Schwaab19 сент. 2018 г., 12:05
Paint.Cap.BUTT по умолчанию, так что вы можете просто удалитьpaint.setStrokeCap(); линия.
 PhoneixS02 июл. 2013 г., 21:22
И если вы используетеpaint.setStrokeCap(Paint.Cap.BUTT); вместоpaint.setStrokeCap(Paint.Cap.ROUND); вы получите именно то, что хочет вопрос.

Вы можете попробовать следовать 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>

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);
 John Perry07 июн. 2017 г., 14:40
Не нужно использоватьlineTo, Для второгоarcTo() добавлятьfalse в качестве конечного параметра; это нарисует линию от конца первой дуги до начала второй. затемclose() путь.
 Snake08 янв. 2015 г., 23:25
Я «думаю», я смутно понял это. Поскольку я все еще нуждаюсь в вашей помощи, я создал другой вопрос, как вы предложили. Ждем вашей помощи. Вот ссылкаstackoverflow.com/questions/27850634/...
 TWiStErRob08 янв. 2015 г., 23:03
@ Змея, тебе придется разделитьsegmentPath.*To() звонки в несколькоPaths и нарисуйте каждый отдельно с выбранными цветами обводки. Вы можете сделать то, что вы описываете, с помощью 2 путей:moveTo,lineTo,moveTo,lineTo а такжеmoveTo,arcTo,moveTo,arcTo, Вам все равно придется сохранить текущий, чтобы что-то заполнить.
 Snake08 янв. 2015 г., 20:39
этот код потрясающий! Однако у меня есть вопрос, есть ли способ сделать так, чтобы линии между кругами имели цвет, отличный от цвета периметра окружностей?

рисование круга и дуги. следующий код немного грязный, но это может помочь

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

Решение Вопроса

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

 znq07 окт. 2010 г., 12:52
Итак, после изучения того, как на самом деле это сделать, я немного растерялся: растровое изображение ARGB8888 - это «нормальное» растровое изображениеgoo.gl/ygTn - и как мне получить те же функции рисования, что и в Canvas?
 znq07 окт. 2010 г., 15:38
Обновление: я понял, что на самом деле могу сделать это следующим образом. Bitmap bm = Bitmap.createBitmap (w, h, Bitmap.Config.ARGB_8888); Холст с = новый холст (бм); а затем нарисуйте на холсте, который будет записывать фактические пиксели на растровое изображение.
 znq06 окт. 2010 г., 19:57
Это возможное решение. Но что делать в том случае, если во внутреннем круге уже нарисовано что-то, что я не хочу перекрашивать и не хочу стирать пиксели и перерисовывать это?
 Romain Guy07 окт. 2010 г., 04:58
Нарисуйте круг в закадровом растровом изображении ARGB8888, сделайте очистку там, а затем нарисуйте растровое изображение на холсте. И таким образом вам также не придется каждый раз перерисовывать круг.

Ваш ответ на вопрос