一:Canvas
Canvas的技巧主要在于以下四个方法:
Canvas.save()
Canvas.restore()
Canvas.translate()
Canvas.rotate()
这一部分并不困难,简单地说一下:
Canvas.save()的效果就如字面的意思,把画布保存起来,让后续所有操作都在新的图层上。
Canvas.restore()的效果则是合并图层,将save()之后的所有图像和save()之前的图像合并。
Canvas.translate()和Canvas.rotate()其实可以理解为坐标系的位移和旋转,通过这两个方法,有些图像的绘制难度会大大降低。
Canvas.translate的参数是(x,y)(x,y是位移目标点的坐标),Canvas.rotate的参数是(旋转角度,旋转中心横坐标,旋转中心纵坐标)
下面上一个例子,是通过以上方法画出一个表盘的。
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,
mWidth / 2, mHeight / 2 - mWidth / 2 + 60,
painDegree);
String degree = String.valueOf(i);
canvas.drawText(degree,
mWidth / 2 - painDegree.measureText(degree) / 2,
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);
}
// 画圆心
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);,re
canvas.save();
canvas.translate(mWidth / 2, mHeight / 2);
canvas.drawLine(0, 0, 100, 100, paintHour);
canvas.drawLine(0, 0, 100, 200, paintMinute);
canvas.restore();
}
}
上述代码是《Android群英传》里的例子,注释已经写得相当清楚了,就不做解释了。
二 Layer图层
Android中一个复杂的图像经常是由多个图层叠加而成,而saveLayer()方法,saveLayerAlpha()方法可以将一个图层入栈,而restore(),restoreToCount()方法会将一个图层出栈。
@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, 0, LAYER_FLAGS);
mPaint.setColor(Color.RED);
canvas.drawCircle(200, 200, 100, mPaint);
canvas.restore();
}
}
这里说一下saveLayerAlpha()方法的参数,前四个参数参照Canvas.drawRect()的前四个,第五个参数是图层透明度(虽说是图层透明度,但经我实验感觉只是对图层上的图像有效果,而不是整个图层),范围是0~225,当127时为半透明,0为彻底透明,255为彻底不透明。
127时的效果图
0时的效果图
255时的效果图