原文链接:http://blog.csdn.net/qibin0506/article/details/48621855
一:复习原作者提到的基础知识:
1、Handler
子线程处理完耗时操作后,通过Message传递数据给Handler,Handler把消息放在主线程队列中,配合主线程更新UI。
Handler有两个作用:
(1):定时执行Message和Runnalbe 对象
(2):让一个动作,在不同的线程中执行。
Tip:
message是放置信息,可以传递一些参数,
Handler获取这些信息并将判度如何处理,
Runnable则是直接给出处理的方法。
2、绘制扇形
在Canvas上绘制扇形的函数:
drawArc( RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)//画弧,
参数一是RectF对象,一个矩形区域椭圆形的界限用于定义在形状、大小、电弧,参数二是起始角(度)在电弧的开始,
参数三扫描角(度)开始顺时针测量的,参数四是如果这是真的话,包括椭圆中心的扇形,并关闭它,如果它是假这将是一个弧线,参数五是Paint对象
建议看这下篇 http://blog.csdn.net/rhljiayou/article/details/7212620
3、Shader类
用于渲染图像以及几何形状,包括:
BitmapShader主要用来渲染图像
LinearGradient 用来进行梯度渲染
RadialGradient 用来进行环形渲染
SweepGradient 用来进行梯度渲染
ComposeShader则是一个 混合渲染,可以和其它几个子类组合起来使用。
使用方法:
先构建Shader对象,然后通过Paint的setShader方法设置渲染对象,然后设置渲染对象,然后再绘制时使用这个Paint对象即可。
建议:http://byandby.iteye.com/blog/831011
4、旋转Canvas类
流程:保存现场——>操作——>恢复现场
canvas.save();
旋转
canvas.restore();
二:Canvas基础例子、
自定义一个View,在onDraw中绘制简单的形状
public class BasicUsageView extends View {
Paint paint1 = new Paint();
Paint paint2 = new Paint();
Paint paint3 = new Paint();
Paint paint4 = new Paint();
public BasicUsageView(Context context){
super(context);
}
public BasicUsageView(Context context,Attributes attributes){
super(context,null);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
initPaint();
drawLine(canvas);
drawRect(canvas);
drawCircle(canvas);
drawText(canvas);
drawImg(canvas);
drawOval(canvas);
drawPathLine(canvas);
drawArc(canvas);
}
private void drawArc(Canvas canvas){
//350, 900 20 250
RectF oval = new RectF(400,500,600,800);
canvas.drawArc(oval,0,20,true,paint1);
canvas.drawArc(oval,60,100,false,paint3);
Shader mShader = new LinearGradient(0,0,100,100, new int[]{Color.BLUE,Color.GREEN,Color.YELLOW,Color.RED},
null,Shader.TileMode.REPEAT);
paint1.setShader(mShader);
canvas.drawArc(oval,110,160,true,paint1);
}
private void drawPathLine(Canvas canvas){
Path path = new Path();
path.moveTo(30, 900);
path.lineTo(50, 700);
path.lineTo(80, 900);
// path.lineTo(30,900);
path.moveTo(30,900);
path.lineTo(100, 900);
path.lineTo(75, 700);
path.lineTo(80, 900);
path.moveTo(100, 900);
path.lineTo(150, 400);
path.lineTo(180, 700);
path.lineTo(220, 370);
path.lineTo(300, 810);
path.lineTo(350, 900);
path.lineTo(100,900);
path.close();
canvas.drawPath(path,paint4);
}
private void drawOval(Canvas canvas){
RectF f = new RectF(300,300,600,500);
canvas.drawOval(f,paint2);
}
private void drawImg(Canvas canvas){
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.img),20,350,paint1);
}
private void drawText(Canvas canvas){
canvas.drawText("这是字符串",10,260,paint4);
}
private void drawCircle(Canvas canvas){
//150,100
canvas.drawCircle(150,100,50,paint3);
canvas.drawCircle(150,100,30,paint4);
}
private void drawRect(Canvas canvas){
canvas.drawRect(30, 30, 290, 190, paint1);
RectF rectF = new RectF(50,50,260,150);
canvas.drawRoundRect(rectF,20,20,paint2);
}
private void drawLine(Canvas canvas){
canvas.drawLine(10,10,310,10,paint1);
canvas.drawLine(10,215,310,215,paint2);
canvas.drawLine(10,10,10,215,paint3);
canvas.drawLine(310,10,310,215,paint4);
}
private void initPaint(){
paint1.setAntiAlias(true);//抗锯齿效果
paint1.setColor(Color.parseColor("#C0FF3E"));//画笔颜色
paint1.setAlpha(79);
paint1.setStyle(Paint.Style.FILL);//实心的
paint1.setStrokeWidth(12);
paint2.setColor(Color.CYAN);
paint2.setTextSize(50);
paint2.setStyle(Paint.Style.STROKE);//空心的
paint2.setStrokeWidth(5);
paint3.setColor(Color.RED);
paint3.setTextSize(100);
paint3.setStyle(Paint.Style.STROKE);//空心的
paint3.setStrokeWidth(2);
paint3.setAntiAlias(false);
paint4.setColor(Color.DKGRAY);
paint4.setTextSize(40);
paint4.setStyle(Paint.Style.STROKE);//空心的
paint4.setStrokeWidth(3);
paint4.setAntiAlias(true);
paint4.setDither(true);//设定是否使用图像抖动处理,会使绘制出来的图片颜色更加平滑和饱满,图像更加清晰
}
}
效果图:
运用到的知识点有:画线、画圆、画矩形、Path路径绘制、画图、椭圆……都很简单
二:Demo的实现、
实现思路:
重写View:
在构造函数中初始化Paint画笔;
在onMeasure方法中测量屏幕宽度,设置矩形面积范围、为paint设置Shader样式;
在onDraw中绘制,原理也就是不断地改变扇形的角度,从0一直增加到360度再归零。为了显示更加逼真,就将Canvas也跟着扇形的角度旋转。在对画布进行操作时,记住要保存现场和恢复现场;
效果实现上,点击自定义View,对Handler发送一个小小,让它一直更新扇形的角度,调用直接在线程中调用postInvalidate()方法刷新View.
public class MyCanvasView extends View {
private static final int MSG_RUN = 1;
private Paint mCirclePaint;
private Paint mArcPaint;
private Paint mLinePaint;
private RectF mRectF;
private int mSweepAngle;
public MyCanvasView(Context context, AttributeSet attrs) {
super(context, attrs);
mCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mArcPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mCirclePaint.setColor(Color.BLACK);
mCirclePaint.setStyle(Style.STROKE);
mCirclePaint.setStrokeWidth(1.f);
mArcPaint.setColor(Color.GRAY);
mArcPaint.setStyle(Style.FILL);
mLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mLinePaint.setColor(Color.BLACK);
mLinePaint.setStrokeWidth(1.f);
mRectF = new RectF();
Log.i("hq"," 构造函数中 mSweepAngle:"+mSweepAngle);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int size = getMeasuredWidth();
setMeasuredDimension(size, size);
mRectF.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
mArcPaint.setShader(new SweepGradient(size/2, size/2, Color.GRAY, Color.BLACK));
}
@Override
protected void onDraw(Canvas canvas) {
int centerX = getMeasuredWidth() / 2;
int centerY = getMeasuredHeight() / 2;
canvas.save();
canvas.rotate(mSweepAngle, centerX, centerY);
canvas.drawArc(mRectF, 0, mSweepAngle, true, mArcPaint);
canvas.restore();
Log.i("hq", "mSweepAngle:" + mSweepAngle);
canvas.drawLine(0, centerY, getMeasuredWidth(), centerY, mLinePaint);
canvas.drawLine(centerX, 0, centerX, getMeasuredHeight(), mLinePaint);
canvas.drawCircle(centerX, centerY, centerX / 2, mCirclePaint);
canvas.drawCircle(centerX, centerY, centerX, mCirclePaint);
}
public void start() {
mHandler.sendEmptyMessage(MSG_RUN);
}
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
if(msg.what == MSG_RUN) {
mSweepAngle+=2;
if(mSweepAngle > 360) mSweepAngle = 0;
postInvalidate();
sendEmptyMessage(MSG_RUN);
}
}
};
}