前面有一篇Android自定义view的官方文章的翻译(英语不好,尽力而为),地址:http://blog.csdn.net/zjqblog/article/details/51026243
代码太多,文章中只贴主要的,这里也共享下demo的github地址:https://github.com/softwater/PieChart
先来看下效果图:
饼图可旋转,也可复位,也就是说可以指定选中某一个扇形。
@Override protected void onDraw(Canvas canvas) { ...... for (Item it : mData) { Log.e(TAG, "item = " + it); mPiePaint.setShader(it.mShader); canvas.drawArc(mBounds, 360 - it.mEndAngle, it.mEndAngle - it.mStartAngle, true, mPiePaint); } }
Item{mLabel='Agamemnon', mValue=2.0, mColor=-3737115, mStartAngle=0, mEndAngle=48, mHighlight=-2228225, mShader=android.graphics.SweepGradient@2311cee0} Item{mLabel='Bocephus', mValue=3.5, mColor=-4789835, mStartAngle=48, mEndAngle=132, mHighlight=-3407926, mShader=android.graphics.SweepGradient@3cdd8599} Item{mLabel='Calliope', mValue=2.5, mColor=-5842507, mStartAngle=132, mEndAngle=192, mHighlight=-4590646, mShader=android.graphics.SweepGradient@165cb05e} Item{mLabel='Daedalus', mValue=3.0, mColor=-6895179, mStartAngle=192, mEndAngle=264, mHighlight=-5709366, mShader=android.graphics.SweepGradient@9e7ec3f} Item{mLabel='Euripides', mValue=1.0, mColor=-7947851, mStartAngle=264, mEndAngle=288, mHighlight=-6893622, mShader=android.graphics.SweepGradient@1974f90c} Item{mLabel='Ganymede', mValue=3.0, mColor=-9000523, mStartAngle=288, mEndAngle=360, mHighlight=-8077878, mShader=android.graphics.SweepGradient@25f7e255}
pie.addItem("Agamemnon", 2, res.getColor(R.color.seafoam));这里设置了每一个扇形的文本内容,所占的大小比重,颜色。
// Calculate the highlight color. Saturate at 0xff to make sure that high values // don't result in aliasing. it.mHighlight = Color.argb(0xff, Math.min((int) (mHighlightStrength * (float) Color.red(color)), 0xff), Math.min((int) (mHighlightStrength * (float) Color.green(color)), 0xff), Math.min((int) (mHighlightStrength * (float) Color.blue(color)), 0xff)); mTotal += value;
/** * Do all of the recalculations needed when the data array changes. */ private void onDataChanged() { Log.e(TAG, "onDataChanged"); // When the data changes, we have to recalculate // all of the angles. int currentAngle = 0; for (Item it : mData) { it.mStartAngle = currentAngle; it.mEndAngle = (int) ((float) currentAngle + it.mValue * 360.0f / mTotal); currentAngle = it.mEndAngle; // Recalculate the gradient shaders. There are // three values in this gradient, even though only // two are necessary, in order to work around // a bug in certain versions of the graphics engine // that expects at least three values if the // positions array is non-null. // it.mShader = new SweepGradient(mPieBounds.width() / 2.0f, mPieBounds.height() / 2.0f, new int[] { it.mHighlight, it.mHighlight, it.mColor, it.mColor, }, new float[] { 0, (float) (360 - it.mEndAngle) / 360.0f, (float) (360 - it.mStartAngle) / 360.0f, 1.0f }); } calcCurrentItem(); onScrollFinished(); }
/** * View that draws the pointer on top of the pie chart */ private class PointerView extends View { /** * Construct a PointerView object */ public PointerView(Context context) { super(context); } @Override protected void onDraw(Canvas canvas) { canvas.drawLine(mTextX, mPointerY, mPointerX, mPointerY, mTextPaint); canvas.drawCircle(mPointerX, mPointerY, mPointerRadius, mTextPaint); } }
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // Draw the shadow canvas.drawOval(mShadowBounds, mShadowPaint); // Draw the label text if (getShowText()) { canvas.drawText(mData.get(mCurrentItem).mLabel, mTextX, mTextY, mTextPaint); } // If the API level is less than 11, we can't rely on the view animation system to // do the scrolling animation. Need to tick it here and call postInvalidate() until the scrolling is done. if (Build.VERSION.SDK_INT < 11) { tickScrollAnimation(); if (!mScroller.isFinished()) { postInvalidate(); } } }drawOval()绘制了饼图下的椭圆,drawText()方法绘制了扇形的名字。
mShadowPaint.setMaskFilter(new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL));