您的位置:首页 > 移动开发 > Android开发

Android之SurfaceView的使用

2016-01-27 12:06 639 查看
使用的一些重点:

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.
b7b8
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();    //必须在此处调用
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Android