1.Canvas的四大金刚
Canvas.save()
这个方法从字面上可以理解为保存画布,作用就是将之前的所有已绘制的图像保存起来。让后续的操作就好像在一个新的图层上操作一样,这一点与Photoshop中的图层理解基本一致。Canvas.restore()
可以理解为Photoshop中的合并图层操作,作用是将我们在save()之后绘制的所有图像与save()之前的图像进行合并。Canvas.translate()
Android默认绘图坐标零点位于屏幕左上角,那么在调用translate()之后,则将零点(0,0)移动到了(x,y)。之后所有绘图操作都将以(x,y)为原点执行。Canvas.rotate()
与translate()同理,旋转坐标系一个一定的角度。
2.Demo:仪表盘
2.1.画外圆
2.2.画刻度和刻度值
2.3.画指针
2.4.全代码和运行结果
Clock.java:
package com.yishengxu.myapplication;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
public class Clock extends View {
private int mHeight, mWidth;
public Clock(Context context) {
super(context);
}
public Clock(Context context, AttributeSet attrs) {
super(context, attrs);
}
public Clock(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onDraw(Canvas canvas) {
// 获取宽高参数
mWidth = getMeasuredWidth();
mHeight = getMeasuredHeight();
// 画外圆
Paint paintCircle = new Paint();
paintCircle.setStyle(Paint.Style.STROKE);
paintCircle.setAntiAlias(true);
paintCircle.setStrokeWidth(5);
canvas.drawCircle(mWidth / 2,
mHeight / 2, mWidth / 2, paintCircle);
// 画刻度
Paint painDegree = new Paint();
paintCircle.setStrokeWidth(3);
for (int i = 0; i < 24; i++) {
// 区分整点与非整点
if (i == 0 || i == 6 || i == 12 || i == 18) {
painDegree.setStrokeWidth(5);
painDegree.setTextSize(30);
canvas.drawLine(mWidth / 2, mHeight / 2 - mWidth / 2,//基线起点x
mWidth / 2, mHeight / 2 - mWidth / 2 + 60,//基线起点y
painDegree);
String degree = String.valueOf(i);//Integer.toString(i)
canvas.drawText(degree,
mWidth / 2 - painDegree.measureText(degree) / 2,//measureText()在画布上输出文本之前,检查字体的宽度:
mHeight / 2 - mWidth / 2 + 90,
painDegree);
} else {
painDegree.setStrokeWidth(3);
painDegree.setTextSize(15);
canvas.drawLine(mWidth / 2, mHeight / 2 - mWidth / 2,
mWidth / 2, mHeight / 2 - mWidth / 2 + 30,
painDegree);
String degree = String.valueOf(i);
canvas.drawText(degree,
mWidth / 2 - painDegree.measureText(degree) / 2,
mHeight / 2 - mWidth / 2 + 60,
painDegree);
}
// 通过旋转画布简化坐标运算
canvas.rotate(15, mWidth / 2, mHeight / 2);//二三参数为枢轴点的xy,枢轴点即旋转中心
}
// 画圆心
Paint paintPointer = new Paint();
paintPointer.setStrokeWidth(30);
canvas.drawPoint(mWidth / 2, mHeight / 2, paintPointer);
// 画指针
Paint paintHour = new Paint();
paintHour.setStrokeWidth(20);
Paint paintMinute = new Paint();
paintMinute.setStrokeWidth(10);
canvas.save();//只是保存“缓冲区”绘制的内容
canvas.translate(mWidth / 2, mHeight / 2);
canvas.drawLine(0, 0, 100, 100, paintHour);
canvas.drawLine(0, 0, 100, 200, paintMinute);
canvas.restore();//将“缓冲区”绘制的内容和已经save()的内容一同合并并保存起来,这里跟上边的save注意区分开来
}
}
MainActivity.java:
package com.yishengxu.myapplication;
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new Clock(this));
}
}
效果图:
3.Layer图层
创建一个新的Layer到“栈”中,可以使用saveLayer(), savaLayerAlpha(), 从“栈”中推出一个Layer,可以使用restore(),restoreToCount()。但Layer入栈时,后续的DrawXXX操作都发生在这个Layer上,而Layer退栈时,就会把本层绘制的图像“绘制”到上层或是Canvas上,在复制Layer到Canvas上时,可以指定Layer的透明度
- 透明度:
- 127,半透明
- 255,完全不透明
- 0,完全透明
实例如Demo下图:
上Demo:
package com.imooc.myapplication;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new MyLayer(this));
}
public class MyLayer extends View {
private Paint mPaint;
private static final int LAYER_FLAGS =
Canvas.MATRIX_SAVE_FLAG |
Canvas.CLIP_SAVE_FLAG |
Canvas.HAS_ALPHA_LAYER_SAVE_FLAG |
Canvas.FULL_COLOR_LAYER_SAVE_FLAG |
Canvas.CLIP_TO_LAYER_SAVE_FLAG;//此乃API定义的常量,ctrl+E 进入文档查看便知晓其含义
public MyLayer(Context context) {
super(context);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.WHITE);//背景
mPaint.setColor(Color.BLUE);
canvas.drawCircle(150, 150, 100, mPaint);//“零图层”
canvas.saveLayerAlpha(0, 0, 400, 400, 127, LAYER_FLAGS);
mPaint.setColor(Color.RED);
canvas.drawCircle(200, 200, 100, mPaint);
canvas.restore();
}
}
}
半透明:
完全不透明: canvas.saveLayerAlpha(0, 0, 400, 400, 255, LAYER_FLAGS);
完全透明: canvas.saveLayerAlpha(0, 0, 400, 400, 0, LAYER_FLAGS);