使用的一些重点:
1.自定义一个View继承于SurfaceView并实现回调(Callback)和OntouchListener
2.自定义draw和clear方法,利用Paint和Path
public class MyView extends SurfaceView implements Callback, OnTouchListener{
private Paint paint = new Paint();
private Path path = new Path();
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
// 添加回调
getHolder().addCallback(this);
// 设置一定的属性
paint.setColor(Color.RED);
paint.setTextSize(10);
paint.setStyle(Style.STROKE);
paint.setAntiAlias(true);
// 设置监听
setOnTouchListener(this);
}
public void draw(){
// 锁定画板
Canvas canvas = getHolder().lockCanvas();
// 进行一定的操作
canvas.drawColor(Color.WHITE);
canvas.drawPath(path, paint);
// 解锁画板
getHolder().unlockCanvasAndPost(canvas);
}
public void clear(){
// 重置,记得调用回draw方法
path.reset();
draw();
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
draw();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
path.moveTo(event.getX(), event.getY());
draw();
break;
case MotionEvent.ACTION_MOVE:
path.lineTo(event.getX(), event.getY());
draw();
break;
}
return true;
}
}
清除画板:
获得MyView实例后调用clear方法即可。
注意点:
1.关于canvas.save()和canvas.restore():
这里canvas.save();和canvas.restore();是两个相互匹配出现的,作用是用来保存画布的状态和取出保存的状态的。
当我们对画布进行旋转,缩放,平移等操作的时候其实我们是想对特定的元素进行操作,比如图片,一个矩形等,但是当你用canvas的方法来进行这些操作的时候,其实是对整个画布进行了操作,那么之后在画布上的元素都会受到影响,所以我们在操作之前调用canvas.save()来保存画布当前的状态,当操作之后取出之前保存过的状态,这样就不会对其他的元素进行影响。
代码段1:
public void draw() {
Canvas canvas = sfh.lockCanvas();
canvas.drawColor(Color.BLACK);
canvas.drawBitmap(bmp1, 0,0,paint);
canvas.save();
canvas.scale(5f, 5f);
canvas.restore();
canvas.drawBitmap(bmp2, 0,0,paint);
sfh.unlockCanvasAndPost(canvas);
}
代码段2:
public void draw() {
Canvas canvas = sfh.lockCanvas();
canvas.drawColor(Color.BLACK);
canvas.drawBitmap(bmp1, 0,0,paint);
canvas.scale(5f, 5f);
canvas.drawBitmap(bmp2, 0,0,paint);
sfh.unlockCanvasAndPost(canvas);
}
上面这两个代码片段中我们都假设有两张图片bmp1和bmp2,并且都画在画布上!
那么代码段1和代码段2的不同:
代码段1中我们进行画布缩放的之前保存了画布状态,做了缩放操作之后又取出之前保存的状态,这样做是为了保证bmp2正常画出来不受到缩放的影响!
代码段2里,画了bmp1后就执行了缩放操作,并且没有保存状态!紧接着画了bmp2,那么bmp2也会一样受到缩放的影响!!
所以我们如果单独处理一张图片的时候,而且不想影响其他部分的绘制,那么应该如下来做:
public void draw() {
Canvas canvas = sfh.lockCanvas();
canvas.drawColor(Color.BLACK);
canvas.drawBitmap(bmp1, 0,0,paint);
canvas.save();
canvas.scale(5f, 5f);
canvas.drawBitmap(bmp2, 0,0,paint);
canvas.restore();
sfh.unlockCanvasAndPost(canvas);
}
2.绘制多个图形并实现动画移动效果
a.可以先新建一个父类Container
public class Container {
private List<Container> children = null;
private float x = 0;
private float y = 0;
public Container() {
children = new ArrayList<Container>();
}
public void childrenView(Canvas canvas) {
};
public void draw(Canvas canvas){
canvas.save();
canvas.translate(getX(), getY()); //控制移动
childrenView(canvas);
for (Container c:children) {
c.draw(canvas);
}
canvas.restore();
}
public void addChildrenView(Container child){
children.add(child);
}
public void deleteChildrenView(Container child){
children.remove(child);
}
public float getX() {
return x;
}
public void setX(float x) {
this.x = x;
}
public float getY() {
return y;
}
public void setY(float y) {
this.y = y;
}
}
b.再建立两个子类继承此父类(以Rect和Circle为例)
public class Rect extends Container{
private Paint paint = null;
public Rect(){
paint = new Paint();
paint.setColor(Color.RED);
}
@Override
public void childrenView(Canvas canvas) {
super.childrenView(canvas);
canvas.drawRect(0, 0, 100, 100, paint);
this.setY(this.getY() + 1);
}
}
public class Circle extends Container{
private Paint paint = null;
public Circle() {
paint = new Paint();
paint.setColor(Color.BLUE);
}
@Override
public void childrenView(Canvas canvas) {
// TODO Auto-generated method stub
super.childrenView(canvas);
canvas.drawCircle(50, 50, 50, paint);
}
}
c.实现效果
public class MyView extends SurfaceView implements SurfaceHolder.Callback{
private Container container;
private Rect rect;
private Circle circle;
public MyView(Context context) {
super(context);
container = new Container();
rect = new Rect();
circle = new Circle();
rect.addChildrenView(circle);
container.addChildrenView(rect);
getHolder().addCallback(this);
}
public void draw(){
Canvas canvas = getHolder().lockCanvas();
canvas.drawColor(Color.WHITE);
container.draw(canvas);
getHolder().unlockCanvasAndPost(canvas);
}
private Timer timer = null;
private TimerTask task = null;
// 实现移动效果
public void startTimer(){
timer = new Timer();
task = new TimerTask() {
@Override
public void run() {
draw();
}
};
timer.schedule(task, 100, 100);
}
public void stopTimer(){
if (timer != null) {
timer.cancel();
timer = null;
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
startTimer(); //必须在此处调用
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
stopTimer(); //必须在此处调用
}
}