最近有看到一个自定义等分圆的View,自己尝试做了一个类似的,效果图如下图(1)所示:
图(1)
实现方法:自定义View-ColorCircle,需要的知道的值有圆的半径,等分个数以及扇形颜色。
/** * 定义几种颜色 */ private static int COLOR[] = {Color.RED, Color.BLUE, Color.GREEN, Color.YELLOW, Color.BLACK}; /** * 圆等分默认数目 */ private static int DIV_SIZE = 3; private Paint mPaint; /** * 圆默认半径 */ private static final int DEFAULT_RADIUS = 200; private int mRadius = DEFAULT_RADIUS; public ColorCircle(Context context) { this(context, null); } public ColorCircle(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public ColorCircle(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mPaint = new Paint(); mPaint.setStyle(Paint.Style.FILL); }
在onMeasure中我们需要根据widthMeasureSpec & heightMeasureSpec重新计算ColorCircle View的尺寸以及圆的半径(因为默认圆的直径可能会大于View的高 or 宽)。
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int widthMode = MeasureSpec.getMode(widthMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); int width; int height; if (widthMode == MeasureSpec.EXACTLY) { width = widthSize; } else { width = mRadius * 2 + getPaddingLeft() + getPaddingRight(); if (widthMode == MeasureSpec.AT_MOST) { width = Math.min(width, widthSize); } } if (heightMode == MeasureSpec.EXACTLY) { height = heightSize; } else { height = mRadius * 2 + getPaddingTop() + getPaddingBottom(); if (heightMode == MeasureSpec.AT_MOST) { height = Math.min(width, heightSize); } } setMeasuredDimension(width, height); mRadius = (int) (Math.min(width - getPaddingLeft() - getPaddingRight(), height - getPaddingTop() - getPaddingBottom()) * 1.0f / 2); }
最后在onDraw里通过canvas.drawArc()来绘制扇形。
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //平移Canvas到屏幕中心,之后的绘制以中心点为初始点 canvas.translate((getWidth() + getPaddingLeft() - getPaddingRight()) / 2, (getHeight() + getPaddingTop() - getPaddingBottom()) / 2); //定义一个RectF对象,表示扇形绘制区域 RectF oval = new RectF(-mRadius, -mRadius, mRadius, mRadius); float firstAngle = 0.0f; float divideAngle = (360 * 1.0f) / DIV_SIZE;//根据DIV_SIZE来算每个扇形的角度 for (int i=0; i<DIV_SIZE; i++) { mPaint.setColor(COLOR[i]); canvas.drawArc(oval, (firstAngle + i * divideAngle), divideAngle, true, mPaint); } } public void setDivSize(int size){ DIV_SIZE = size; invalidate(); } public int getDivSize(){ DIV_SIZE = size; }
最后还预留了一个setDivSize()接口,方便自定义ColorCircle View动态变化扇形数目。我这里是通过Seekbar来动态切换DIV_SIZE。
mColorCircle = (ColorCircle)findViewById(R.id.color_circle); mSeekBar = (SeekBar)findViewById(R.id.seek_bar); mSeekBar.setMax(4);//因为颜色数目原因,这里seekBar的最大值设置为了4。 int pro = mColorCircle.getSize(); mSeekBar.setProgress(pro); mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { mColorCircle.setDivSize(progress + 1); } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { } });
效果图如下:
时间: 2024-10-10 02:06:18