自定义圆圈,中间有空格

时间:2015-12-05 10:22:02

标签: android android-canvas android-custom-view ondraw

我正在尝试使用Circle的自定义视图,并且我必须在运行时给出部分,如下图所示。我在onDraw方法中尝试了很多东西,但没有运气。即使我引用这个https://github.com/donvigo/CustomProgressControls。基本上我想要给出部分然后每个部分我可以根据需要给出颜色。

enter image description here

我正在寻找进度条应该有间隙/空间如图所示,如果我已经给出第5节然后它应该有5节然后说如果我只填充3节那么它将变为全红到1 -3部分,如果它传递到4部分,则所有1-4变为绿色,同样为第5部分

画我喜欢:

private void initExternalCirclePainter() {
    internalCirclePaint = new Paint(); 
    internalCirclePaint.setAntiAlias(true);    
    internalCirclePaint.setStrokeWidth(internalStrokeWidth);  
    internalCirclePaint.setColor(color); 
    internalCirclePaint.setStyle(Paint.Style.STROKE);
    internalCirclePaint.setPathEffect(new DashPathEffect(new float[]{dashWith, dashSpace}, dashSpace));
} 

2 个答案:

答案 0 :(得分:0)

我发现更容易对drawArc进行数学运算(根据截面数操作角度值)而不是计算弧长。 这是一个快速的想法,有很多硬编码的属性,但你应该能够理解:

public class MyStrokeCircleView extends View {
    private Paint mPaint;
    private RectF mRect;
    private int mPadding;

    private int mSections;
    private int mFullArcSliceLength;
    private int mColorArcLineLength;
    private int mArcSectionGap;

    public MyStrokeCircleView(Context context) {
        super(context);
        init(null, 0);
    }

    public MyStrokeCircleView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(attrs, 0);
    }

    public MyStrokeCircleView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(attrs, defStyle);
    }

    private void init(AttributeSet attrs, int defStyle) {
        mPaint = new Paint();
        mPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(10);
        mPaint.setColor(ContextCompat.getColor(getContext(), android.R.color.darker_gray));

        mPadding = 5;
        mRect = new RectF(mPadding, mPadding, mPadding, mPadding);

        mSections = 4;
        mFullArcSliceLength = 360 / mSections;
        mArcSectionGap = mFullArcSliceLength / 10;
        mColorArcLineLength = mFullArcSliceLength - 2 * mArcSectionGap;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mRect.right = getWidth() - mPadding;
        mRect.bottom = getHeight() - mPadding;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        for (int i = 0; i < mSections; i++) {
            canvas.drawArc(mRect, i * mFullArcSliceLength + mArcSectionGap, mColorArcLineLength, false, mPaint);
        }
    }
}

答案 1 :(得分:0)

我参加聚会可能有点晚了,但我实际上编写了一个自定义组件,它有 2 个环,看起来与您想要实现的非常相似。您可以轻松地卸下外圈。最后得到的图:

enter image description here

这是课程:

public class RoundedSectionProgressBar extends View {
// The amount of degrees that we wanna reserve for the divider between 2 sections
private static final float DIVIDER_ANGLE = 7;
public static final float DEGREES_IN_CIRCLE = 360;
public static final int PADDING = 18;
public static final int PADDING2 = 12;

protected final Paint paint = new Paint();
protected final Paint waitingPaint = new Paint();
protected final Paint backgroundPaint = new Paint();
private int totalSections = 5;
private int fullSections = 2;
private int waiting = 3; // The outer ring. You can omit this
private RectF rect = new RectF();

public RoundedSectionProgressBar(Context context) {
    super(context);
    init(context, null);
}

public RoundedSectionProgressBar(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    init(context, attrs);
}

public RoundedSectionProgressBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init(context, attrs);
}

private void init(Context context, AttributeSet attrs) {
    // Can come from attrs if need be?
    int strokeWidth = 3;
    setupPaint(context, strokeWidth, paint, R.color.filled_color_inner_ring);
    setupPaint(context, strokeWidth, waitingPaint, R.color.empty_color_inner_ring);
    setupPaint(context, strokeWidth, backgroundPaint, R.color.filled_color_outer_ring);
}

private void setupPaint(Context context, int strokeWidth, Paint backgroundPaint, int colorRes) {
    backgroundPaint.setStrokeCap(Paint.Cap.SQUARE);
    backgroundPaint.setColor(context.getResources().getColor(colorRes));
    backgroundPaint.setAntiAlias(true);
    backgroundPaint.setStrokeWidth(strokeWidth);
    backgroundPaint.setStyle(Paint.Style.STROKE);
}

public int getTotalSections() {
    return totalSections;
}

public void setTotalSections(int totalSections) {
    this.totalSections = totalSections;
    invalidate();
}

public int getFullSections() {
    return fullSections;
}

public void setNumberOfSections(int fullSections, int totalSections, int waiting) {
    this.fullSections = fullSections;
    this.totalSections = totalSections;
    this.waiting = waiting;
    invalidate();
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    rect.set(getLeft() + PADDING, getTop() + PADDING, getRight() - PADDING, getBottom() - PADDING);
    float angleOfSection = (DEGREES_IN_CIRCLE / totalSections) - DIVIDER_ANGLE;
    // Drawing the inner ring
    for (int i = 0; i < totalSections; i++) {
        // -90 because it doesn't start at the top, so rotate by -90
        // divider_angle/2 especially in 2 sections, it's visibly rotated by Divider angle, so we split this between last and first
        float startAngle = -90 + i * (angleOfSection + DIVIDER_ANGLE) + DIVIDER_ANGLE / 2;
        if (i < fullSections) {
            canvas.drawArc(rect, startAngle, angleOfSection, false, paint);
        } else {
            canvas.drawArc(rect, startAngle, angleOfSection, false, backgroundPaint);
        }
    }
    // Drawing the outer ring
    rect.set(getLeft() + PADDING2, getTop() + PADDING2, getRight() - PADDING2, getBottom() - PADDING2);
    for (int i = 0; i < waiting; i++) {
        float startAngle = -90 + i * (angleOfSection + DIVIDER_ANGLE) + DIVIDER_ANGLE / 2;
        canvas.drawArc(rect, startAngle, angleOfSection, false, waitingPaint);
    }
}
}
<块引用>

请注意,此代码不会为您提供外环的“空”插槽,因为我们最终决定反对它们。内圈将同时具有空槽和已填充槽。整个类可以重用,它只负责绘制的 2 个环,6/6+3 和红色圆圈是另一个视图的一部分。

代码中最重要的部分是 onDraw 方法。它包含在 for 循环中绘制弧线的逻辑,以及计算角度和在它们之间添加空间的逻辑。一切都旋转了 -90 度,因为我需要它从顶部开始,而不是从右侧开始,因为它是 Android 中的 0 度角。它并不复杂,您可以根据需要对其进行修改以更好地满足您的需求。