Android SurfaceView使用
与View区别
更新View任务太重会导致UI线程阻塞
而SurfaceView不会,可以在UI线程之外更新UI
工程代码 SurfaceViewDemo.zip
----------------------------------------------
1. 使用SurfaceView 要点
2. 创建单个图形
3. 创建多个图形
4. 绘制组合图形
5. 使4中的组合图形动起来
----------------------------------------------
1. 使用SurfaceView 要点
* 通过 SurfaceHolder 控制Surface
* 一定是在Surface创建之后开始画布操作, 一定在Surface创建之前结束画布操作
集成 SurfaceView类,实现 SurfaceHolder.Callback 接口
在构造函数中调用: getHolder().addCallback(this);
框架如下:
public class MyView extends SurfaceView implements SurfaceHolder.Callback { // 通过 SurfaceHolder 控制Surface public MyView(Context context) { super(context); getHolder().addCallback(this); } public void draw() { // 一定是在Surface创建之后开始画布操作 Canvas canvas = getHolder().lockCanvas(); // start // end, 一定在Surface创建之前结束画布操作 getHolder().unlockCanvasAndPost(canvas); } @Override public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) { // Surface 改变的时候触发 } @Override public void surfaceCreated(SurfaceHolder holder) { draw(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { // TODO Auto-generated method stub } }
2. 创建单个图形
修改如下,声明画笔 paint, 然后画一个红色的矩形
private Paint paint = null; public MyView(Context context) { super(context); // TODO Auto-generated constructor stub paint = new Paint(); paint.setColor(Color.RED); getHolder().addCallback(this); } public void draw() { // 一定是在Surface创建之后开始画布操作 Canvas canvas = getHolder().lockCanvas(); // start canvas.drawColor(Color.WHITE); canvas.drawRect(0, 0, 100, 100, paint); // end, 一定在Surface创建之前结束画布操作 getHolder().unlockCanvasAndPost(canvas); }
3. 创建多个图形
绘制两条垂直90度的直线,三个重要的步骤
canvas.save();// 保存成可编辑状态
canvas.rotate(90, getWidth()/2, getHeight()/2); //画布旋转90度
canvas.restore(); //重新恢复画布到正常状态(旋转前),否则影响后面的绘制
public void draw() { // 一定是在Surface创建之后开始画布操作 Canvas canvas = getHolder().lockCanvas(); // start canvas.drawColor(Color.WHITE); canvas.save();// 保存成可编辑状态 canvas.rotate(90, getWidth()/2, getHeight()/2); //画布旋转90度 canvas.drawLine(0, getHeight()/2, getWidth(), getHeight(), paint); canvas.restore(); //重新恢复画布到正常状态(旋转前) canvas.drawLine(0, getHeight()/2 + 100, getWidth(), getHeight()+100, paint); // end, 一定在Surface创建之前结束画布操作 getHolder().unlockCanvasAndPost(canvas); }
4. 绘制组合图形
创建容器 Container 类: 可以添加、删除子视图, 绘制view
创一个矩形Rec:
创建 圆 Circle:
在控件MyView中,添加一个容器,容器中放置一个矩形,矩形内放一个圆
public class Container { private List<Container> children = null; public Container() { children = new ArrayList<Container>(); } public void draw(Canvas canvas) { childrenView(canvas); for (Container c : children) { c.draw(canvas); } } public void addChirdrenView(Container c) { children.add(c); } public void removeChirdrenView(Container c) { children.remove(c); } public void childrenView(Canvas canvas) { // TODO Auto-generated method stub } }
public class Rect extends Container { private Paint paint; 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); } }
public class Circle extends Container { private Paint paint; public Circle(){ paint = new Paint(); paint.setColor(Color.BLUE); } @Override public void childrenView(Canvas canvas) { // super.childrenView(canvas); canvas.drawCircle(60, 60, 50, paint); } }
public class MyView extends SurfaceView implements SurfaceHolder.Callback { // 通过 SurfaceHolder 控制Surface private Container container; private Rect rect; private Circle circle; public MyView(Context context) { super(context); // TODO Auto-generated constructor stub container = new Container(); rect = new Rect(); circle = new Circle(); rect.addChirdrenView(circle); container.addChirdrenView(rect); getHolder().addCallback(this); } @Override public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) { // Surface 改变的时候触发 draw() ; } @Override public void surfaceCreated(SurfaceHolder holder) { // TODO Auto-generated method stub } @Override public void surfaceDestroyed(SurfaceHolder holder) { // TODO Auto-generated method stub } public void draw() { // 一定是在Surface创建之后开始画布操作 Canvas canvas = getHolder().lockCanvas(); // start canvas.drawColor(Color.WHITE); container.draw(canvas); // end, 一定在Surface创建之前结束画布操作 getHolder().unlockCanvasAndPost(canvas); } }
5. 使4中的组合图形动起来
修改容器类Container:
public void draw(Canvas canvas) { canvas.save(); canvas.translate(getX(), getY()); childrenView(canvas); for (Container c : children) { c.draw(canvas); } canvas.restore(); }
修改矩形:
public void childrenView(Canvas canvas) { super.childrenView(canvas); canvas.drawRect(0, 0, 100, 100, paint); this.setY(this.getY()+3); }
在 MyView 控件中增加timer
private Timer timer = null; private TimerTask task = null; public void startTimer(){ timer = new Timer(); task = new TimerTask() { @Override public void run() { // TODO Auto-generated method stub draw(); } }; timer.schedule(task, 100, 100); //每100ms执行一次 } public void stopTimer(){ if (timer != null) { timer.cancel(); timer = null; } }
@Override public void surfaceCreated(SurfaceHolder holder) { // surface 创建之后 startTimer(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { // surface 销毁之前 stopTimer(); } @Override protected void onDetachedFromWindow() { // TODO Auto-generated method stub stopTimer(); //不加这句,应用程序退出时会死 super.onDetachedFromWindow(); }
工程代码 SurfaceViewDemo.zip