android自定义view分子式,Android自定义view实例PieChart分析

概览

先来看下效果图:

0818b9ca8b590ca3270a3433284dd417.png

饼图可旋转,也可复位,也就是说可以指定选中某一个扇形。

图形结构

图形由文字及饼图下的椭圆,小圆点和线(PieChart.PointerView),饼图(PieChart.PieView)组成。

饼图PieView的绘制

PieView继承自View,在onDraw()方法中实现了饼图的绘制:

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

}

}

主要是其中的drawArc方法,所以PieView就是几个扇形拼凑起来的。

下面是输出的Item的内容:

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}

在MainActivity中对Item进行了赋值,下面取出其中的一个:

pie.addItem("Agamemnon", 2, res.getColor(R.color.seafoam));这里设置了每一个扇形的文本内容,所占的大小比重,颜色。

在addItem方法里计算了颜色高亮的值,统计了所有扇形大小比重的总和。

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

每次改变了存放扇形Item的集合的时候都要调用onDataChanged()方法进行重新计算。

/**

* 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();

}

小圆点和线(PieChart.PointerView)的绘制

很简单,使用canvas调用drawLine()绘制线,调用drawCircle()绘制圆点。

/**

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

}

}

文字及饼图下的椭圆的绘制

在PieChart中有这样一个方法:

@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()方法绘制了扇形的名字。

在旋转的时候扇形下的椭圆会发生变化,是因为在init方法里设置了如下代码:

mShadowPaint.setMaskFilter(new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL));

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值