Canvas
Canvas绘图有三个基本要素:Canvas、绘图坐标系以及Paint。Canvas是画布,我们通过Canvas的各种drawXXX方法将图形绘制到Canvas上面,在drawXXX方法中我们需要传入要绘制的图形的坐标形状,还要传入一个画笔Paint。drawXXX方法以及传入其中的坐标决定了要绘制的图形的形状。
两种坐标系:Canvas坐标系与绘图坐标系。
Canvas坐标系
Canvas坐标系指的是Canvas本身的坐标系,Canvas坐标系有且只有一个,且是唯一不变的,其坐标原点在View的左上角,从坐标原点向右为x轴的正半轴,从坐标原点向下为y轴的正半轴。
绘图坐标系
默认情况下,绘图坐标系与Canvas坐标系完全重合。绘图坐标系并不是一成不变的,可以通过调用Canvas的translate方法平移坐标系,可以通过Canvas的rotate方法旋转坐标系,还可以通过Canvas的scale方法缩放坐标系,translate、rotate、scale的操作都是基于当前绘图坐标系的,一旦通过以上方法对坐标系进行了操作之后,当前绘图坐标系就变化了,以后绘图都是基于更新的绘图坐标系了。也就是说,真正对我们绘图有用的是绘图坐标系而非Canvas坐标系。
简单画图
在MainActivity中,我们创建一个自定义View对象,使用onDraw方法提供的Canvas进行绘制图形。
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new CustomView1(this));
}
class CustomView1 extends View{
Paint paint;
public CustomView1(Context context) {
super(context);
paint = new Paint(); //设置一个笔刷大小是3的黄色的画笔
paint.setColor(Color.YELLOW);
paint.setStrokeJoin(Paint.Join.ROUND);//设置线段连接处样式
paint.setStrokeCap(Paint.Cap.ROUND);//设置线冒样式,取值有Cap.ROUND(圆形线冒)、Cap.SQUARE(方形线冒)、Paint.Cap.BUTT(无线冒)
paint.setStrokeWidth(3);
}
//在这里我们将测试canvas提供的绘制图形方法
@Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.RED); //绘制背景颜色为红色
}
}
}
对Canvas进行操作
drawLine
canvas.drawLine(10, 10, 100, 100, paint); //from x,y to x,y
drawCircle
canvas.drawCircle(100, 100, 90, paint); //画一个圆形,圆心x,y ,半径r
drawOval
//定义一个矩形区域
RectF oval = new RectF(0,0,200,300);//left,top,right,bottom
//矩形区域内切椭圆
canvas.drawOval(oval, paint);
drawRect
RectF rect = new RectF(50, 50, 200, 200); // left,top,right,bottom
canvas.drawRect(rect, paint);//矩形
drawRoundRect
RectF rect = new RectF(50, 50, 200, 200);
canvas.drawRoundRect(rect,
30, //x轴的半径,圆角矩形
30, //y轴的半径
paint);
drawPoint
canvas.drawPoint(60, 390, paint);//画一个点
/**
* 参数1:多个点,每两个值为一个点。最后个数不够两个的值,忽略。
*/
canvas.drawPoints(new float[]{60,400,65,400,70,400}, paint);//画多个点
translate、scale、rotate
canvas.translate(100, 50);//向X轴方向移动100距离 ,向Y轴方向移动50距离
canvas.scale(2, 4);//X轴的放大倍数2,Y轴的放大倍数4
canvas.rotate(30);//原点为中心,旋转30度(顺时针方向为正方向 )
canvas.rotate(30,100,100);//以(100,100)为中心,旋转30度,顺时针方向为正方向
关于Paint
要绘图,首先得调整画笔,待画笔调整好之后,再将图像绘制到画布上,这样才可以显示在手机屏幕上。
在Android中需要通过graphics类来显示2D图形
graphics中包括了Canvas(画布)、Paint(画笔)、Color(颜色)、Bitmap(图像)等常用的类。graphics具有绘制点、线、颜色、2D几何图形、图像处理等功能。
自定义View的基本实现方法
首先,我们需要自定义一个类,比如MyView,继承于View类。然后,复写View类的onDraw()函数。最后,在onDraw()函数中使用Paint和Canvas对象绘制我们需要的图形。
实例:矩阵移动
public class MoveRectView extends View {
private int count=0;
public MoveRectView (Context context) {
super(context);
setFocusable(true); //聚焦设置
setFocusableInTouchMode(true);
}
protected void onDraw(Canvas canvas) {
if(count<100){
count++;
}else{
count=0;
}
Paint paint=new Paint();
paint.setStrokeWidth(3.0f); //矩形移动
canvas.drawRect(count*20, 100,count*20+50 , 150,paint);// 画圆,圆心的坐标(cx,cy)和半径radius
}
}
在MainActivity中使用矩形移动
private MoveRectView moveRectView ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
signalView=new SignalLightView(this);
setContentView(R.layout.activity_main);
RelativeLayout layout=(RelativeLayout) findViewById(R.id.main);
layout.addView(moveRectView);
new Thread(new SignalLightThread()).start();
}
class SignalLightThread implements Runnable{
@Override
public void run() {
while(!Thread.currentThread().isInterrupted()){
try {
Thread.sleep(150);
} catch (InterruptedException e) {
e.printStackTrace();
}
moveRectView.postInvalidate();//使得原来的View重绘即重新调用onDraw方法
}
}
}
View的效果是在onDraw中完成的,其中一种方式就是通过调用invalidate方法(主线程中是通过invalidate方法;子线程里则是调用postInvalidate)我们主动去通过自定义View去调用invalidate方法致使Canvas失效,Android就会自动再去触发onDraw方法。