Android之SurfaceView的使用
2016-01-27 12:06
639 查看
使用的一些重点:
1.自定义一个View继承于SurfaceView并实现回调(Callback)和OntouchListener
2.自定义draw和clear方法,利用Paint和Path
清除画板:
获得MyView实例后调用clear方法即可。
注意点:
1.关于canvas.save()和canvas.restore():
这里canvas.save();和canvas.restore();是两个相互匹配出现的,作用是用来保存画布的状态和取出保存的状态的。
当我们对画布进行旋转,缩放,平移等操作的时候其实我们是想对特定的元素进行操作,比如图片,一个矩形等,但是当你用canvas的方法来进行这些操作的时候,其实是对整个画布进行了操作,那么之后在画布上的元素都会受到影响,所以我们在操作之前调用canvas.save()来保存画布当前的状态,当操作之后取出之前保存过的状态,这样就不会对其他的元素进行影响。
代码段1:
代码段2:
上面这两个代码片段中我们都假设有两张图片bmp1和bmp2,并且都画在画布上!
那么代码段1和代码段2的不同:
代码段1中我们进行画布缩放的之前保存了画布状态,做了缩放操作之后又取出之前保存的状态,这样做是为了保证bmp2正常画出来不受到缩放的影响!
代码段2里,画了bmp1后就执行了缩放操作,并且没有保存状态!紧接着画了bmp2,那么bmp2也会一样受到缩放的影响!!
所以我们如果单独处理一张图片的时候,而且不想影响其他部分的绘制,那么应该如下来做:
2.绘制多个图形并实现动画移动效果
a.可以先新建一个父类Container
b.再建立两个子类继承此父类(以Rect和Circle为例)
c.实现效果
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(); //必须在此处调用 } }
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories