http://orgcent.com/android-custom-view-draw-mechanism/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec); //获取ViewGroup宽度
int height = MeasureSpec.getSize(heightMeasureSpec); //获取ViewGroup高度
setMeasuredDimension(width, height); //设置ViewGroup的宽高
int childCount = getChildCount(); //获得子View的个数,下面遍历这些子View设置宽高
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
child.measure(viewWidth, viewHeight); //设置子View宽高
}
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
int mTotalHeight = 0;
// 当然,也是遍历子View,每个都要告诉ViewGroup
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View childView = getChildAt(i);
// 获取在onMeasure中计算的视图尺寸
int measureHeight = childView.getMeasuredHeight();
int measuredWidth = childView.getMeasuredWidth();
childView.layout(left, mTotalHeight, measuredWidth, mTotalHeight + measureHeight);
mTotalHeight += measureHeight;
}
}
// 绘制前景图 ,新画上去的图片可以理解为前景,就是src。
paint = new Paint();
paint.setColor(Color.WHITE);
paint.setAntiAlias(true);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
// 绘制背景图 ,canvas原有的图片可以理解为背景,就是dst;
paint2 = new Paint();
paint2.setXfermode(null);
Rect参数的意思代表的是矩形的左上角的坐标(left、top)和右下角的坐标(right、bottom)
由两点的位置确定了矩形的高和宽
高:bottom-top
宽:right-left
public void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)
oval :指定圆弧的外轮廓矩形区域。
startAngle: 圆弧起始角度,单位为度。
sweepAngle: 圆弧扫过的角度,顺时针方向,单位为度。
useCenter: 如果为True时,在绘制圆弧时将圆心包括在内,通常用来绘制扇形。
paint: 绘制圆弧的画板属性,如颜色,是否填充等。
当recycle被调用后,这就说明这个对象从现在可以被重用了。
原文地址:http://www.cnblogs.com/kissazi2/p/4049982.html
原理说明:http://www.haodaima.net/art/2603825 讲的好!
最复杂的地方就是画刻度了,这里要先复习一下数学中的三角函数:
刻度的起始位置就是圆框上的一个点,第一步就是要知道这个点的坐标。上图中:
sinθ = AC / AO
cosθ = OC / AO
其中AO即为圆半径,而θ的值则根据刻度而定。0是π/2,3是0,6是3π/2,9是π:
由此可得到刻度起始点的位置为:
x = 圆点横坐标 + AO * cosθ
y = 圆点纵坐标 + AO * sinθ
同理可算出刻度结束点的位置为(结束点相当于在一个半径为圆框半径-刻度长度的圆上):
x = 圆点横坐标 + (AO - 刻度长度) * cosθ
y = 圆点纵坐标 + (AO - 刻度长度) * sinθ
于是,这程序可以写了:
for (var i = 0, angle = 0, tmp, len; i < 60; i++) {
bgCtx.beginPath();
// 突出显示能被5除尽的刻度
if (0 === i % 5) {
bgCtx.lineWidth = 5;
len = 12;
bgCtx.strokeStyle = '#000';
} else {
bgCtx.lineWidth = 2;
len = 6;
bgCtx.strokeStyle = '#999';
}
tmp = radius - borderWidth / 2; // 因为圆有边框,所以要减去边框宽度
bgCtx.moveTo(
dot.x + tmp * Math.cos(angle),
dot.y + tmp * Math.sin(angle)
);
tmp -= len;
bgCtx.lineTo(dot.x + tmp * Math.cos(angle), dot.y + tmp * Math.sin(angle));
bgCtx.stroke();
bgCtx.closePath();
angle += Math.PI / 30; // 每次递增1/30π
}
正玄定理余玄定理回顾:http://baike.baidu.com/link?url=a2JC6gyPPQh2ZOQ6UJjrcpvNeaG6mPeXLWVoix6u7E3FhOG4NynGdTyl61VosvO4
该方法的声明为:
void android.graphics.Path.arcTo(RectF oval, float startAngle, float sweepAngle);
该方法是画一个弧线的路径.
第一个参数是一个RectF类型.这个参数是干嘛的呢?
先说一下,这个弧线是怎么来的?是先画一个椭圆,然后再在这个椭圆上面截取一部分部形。这个图形自然就是一个弧线了。那么这个椭圆是怎么确定的呢?这就是这个rectF参数所起的作用了。
如图所示:
给出这个矩形后,系统就可以算出这个矩形的中心,然后以这个矩开的中心画一个椭圆。
得到这个椭圆后,然后就是截取一部分线了,就得到最终的弧线。这一部分是怎么截取的呢?
这就是后面两个参数共同来表达的。
startAngle这个参数说的是开始的角度。这个好理解,但哪里是0度线呢,又是向哪个方向旋转是正角度数呢?下面由图形来展示:
图上所示的红线就是0度线。
startAngle是开始度数,那sweepAngle是指的什么呢?
sweepAngle指的是旋转的度数,也就是以startAngle开始,旋转多少度,如果sweepAngle是正数,那么就是按顺时针方向旋转,如果是负数就是按逆时针方向旋转。
如果示例:startAngle = 0; sweepAngle=90时:
红色部分的弧线就是最终的弧线...
http://blog.csdn.net/harvic880925/article/details/39080931