自己对这个几个方法,用了好多次了,但对它们的原理概念都还是没仔细理解清楚,真是太菜了。
View和canvas并不是同一个东西,可以这样想象,我们的View是固定的,相当于与一个画板或者画框,画板范围就是View的矩形范围,canvas是画布,我们在画布上画东西,最后呈现到画板也就是View上。一开始View和Canvas的坐标是对齐的,也就是画布的右上角就是画框的右上角,四条边都是对齐的。然后canvas是可以变换的,我们平移canvas dx,dy,然后draw画图,就相当于把画布拖动一段距离,然后作画,作画的时候坐标系是按着画布来的,跟View没有关系。最后,最后画布上的东西按照画布的位置直接映射到View画板上,就是移动了的图像。同样的旋转就相当于把画布上的图转动了,默认原点,也可设置点。 对于缩放,要理解一下,就是画的图以某个点为中心放大或者缩小。
一个小技巧:我们思考这几个变换叠加起来的效果的时候,总是容易按照api的顺序,先思考画布变化之后,图像怎么画上去,有时候很难想,感觉这是Android api先变画布,在作画这种顺序设置的局限吧,应该倒过来想才对,是图像画到画布上去之后,把画布进行变化,这样想起来简单多了。比如下面的例子
(不过要注意的是,canvas的变换是影响后面draw的图,不影响前面画好的的图,也是是canva调用draw的时候,相当于画版就把画取走了,后面的canvas是一张白布。所有的图像在View这个画框上面叠加,画框外的图是看不到的。)
canvas多次变化,比如平移,缩放,旋转,就相当于带着所画的图平移,缩放,旋转
以下内容转载别人的:
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
//translate 平移,即改变坐标系原点位置
Paint paint = new Paint();
paint.setColor(Color.GREEN);
paint.setStyle(Style.FILL);
// canvas.translate(100, 100);
Rect rect1 = new Rect(0,0,400,220);
canvas.drawRect(rect1, paint);
}
旋转:
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
Paint paint_green = generatePaint(Color.GREEN, Style.FILL, 5);
Paint paint_red = generatePaint(Color.RED, Style.STROKE, 5);
Rect rect1 = new Rect(300,10,500,100);
canvas.drawRect(rect1, paint_red); //画出原轮廓
canvas.rotate(30);//顺时针旋转画布
canvas.drawRect(rect1, paint_green);//画出旋转后的矩形
}
效果图是这样的:
缩放:
Paint mPaint = new Paint();
canvas.drawColor(Color.BLUE);
mPaint.setColor(Color.GRAY);
canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);
// 保存画布状态
canvas.save();
canvas.scale(0.5f, 0.5f, 200, 200);
mPaint.setColor(Color.RED);
canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);
Canvas.scale (float sx, float sy, float px, float py) 源码如下:
/**
- Preconcat the current matrix with the specified scale.
- @param sx The amount to scale in X
- @param sy The amount to scale in Y
- @param px The x-coord for the pivot point (unchanged by the scale)
- @param py The y-coord for the pivot point (unchanged by the scale)
/
public final void scale(float sx, float sy, float px, float py) {
translate(px, py);
scale(sx, sy);
translate(-px, -py);
}
translate(px, py)移动的物理距离分别是px和py,经过scale(sx, sy)缩放后再通过translate(-px, -py)位移,移动的物理距离就是-pxsx和-py*sy。