当前位置:
文档之家› android的图像图像绘图-surfaceview
android的图像图像绘图-surfaceview
2013-12-13
SurfaceView绘图机制
• 重写CallBack对象的surfaceCreate方法 ,在该方法中为SurfaceView绘制背景 ,并避免背景图片被下一次 lockCanvas遮挡。 监听触摸事件,每次触摸屏幕时,程 序会锁定触碰周围的区域,那么就只 更新该区域的数据,而且本次的 lockCanvas会遮挡上一次的lockCanvas 后绘制的图形。 注:第一次绘制的图形可能会被第二 次的lockCanvas遮挡,第三次的 lockcanvas又可能遮挡第二次 lockCanvas的区域,但不可能遮挡第 一次的lockCanvas区域
2013-12-13
SurfaceView绘图机制
sf.setOnTouchListener(new OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { if(event.getAction()==MotionEvent.ACTION_DOWN){ int cx=(int) event.getX(); int cy=(int) event.getY(); Canvas canvas=holder.lockCanvas(new Rect(cx-50,cy-50,cx+50,cy+50)); canvas.save(); canvas.rotate(30, cx, cy); paint.setColor(Color.YELLOW); canvas.drawRect(cx-40, cy-40, cx, cy, paint); canvas.restore(); paint.setColor(Color.GREEN); canvas.drawRect(cx, cy, cx+40, cy+40, paint); holder.unlockCanvasAndPost(canvas); } return false; } });
使用SurfaceView绘制矩形
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new MyView(this)); } class MyView extends SurfaceView implements SurfaceHolder.Callback{ SurfaceHolder holder; public MyView(Context context) { super(context); holder=getHolder(); holder.addCallback(this); } } public void surfaceCreated(SurfaceHolder holder) { new Thread(new MyThread()).start(); }
•
•
2013-12-13
callback接口
• 只要继承SurfaceView类并实现SurfaceHolder.Callback接口就可以实 现一个自定义的SurfaceView,SurfaceHolder.Callback在底层的 Surface状态发生变化的时候通知View,SurfaceHolder.Callback具有 如下的接口: surfaceCreated(SurfaceHolder holder):当Surface第一次创建后会立 即调用该函数。程序可以在该函数中做些和绘制界面相关的初始化工 作,一般情况下都是在另外的线程来绘制界面,所以不要在这个函数 中绘制Surface。 surfaceChanged(SurfaceHolder holder, int format, int width,int height) :当Surface的状态(大小和格式)发生变化的时候会调用该函数, 在surfaceCreated调用后该函数至少会被调用一次。
•
•
SurfaceView绘图机制
holder.addCallback(new Callback() { public void surfaceDestroyed(SurfaceHolder holder) {} public void surfaceCreated(SurfaceHolder holder) { Canvas canvas=holder.lockCanvas(); Bitmap bitmap=BitmapFactory.decodeResource(MainActivity.this.getResources(), R.drawable.sun); canvas.drawBitmap(bitmap, 0, 0, null); holder.unlockCanvasAndPost(canvas); holder.lockCanvas(new Rect(0,0,0,0)); holder.unlockCanvasAndPost(canvas); } public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {} });
android的图像图像-SurfaceView类
2013-12-13
View和SurfaceView
• View类是android的一个超类,每一个View都有一个用于绘画的画布, 这个画布可以进行任意的扩展。有的时候我们需要自定义VIew实现自 己想要的视图。view、SurfaceView是游戏开发中经常用到的视图。 View:显示视图,内置画布,提供图形绘制函数、触屏事件、按键事 件函数等;必须在UI主线程内更新画面,速度较慢。 SurfaceView:基于view视图进行拓展的视图类,更适合2D游戏的开发 ;是view的子类,类似使用双缓机制,在新的线程中更新画面所以刷 新界面速度比view快。
2013-12-13
使用SurfaceView绘制矩形
class MyThread implements Runnable{ public void run() { //锁定画布,通过其返回的画布对象canvas,在其上面画图 Canvas canvas=holder.lockCanvas(); canvas.drawColor(Color.WHITE); Paint paint=new Paint(); paint.setColor(Color.YELLOW); canvas.drawRect(10, 10, 220, 180, paint); holder.unlockCanvasAndPost(canvas);//结束锁定画图,并提交编辑 } }
• SurfaceView和View最本质的区别在于,surfaceView是在一个新起的单独线程中 可以重新绘制画面,而View必须在UI的主线程中更新画面。那么在UI的主线程 中更新画面 可能会引发问题,比如更新画面的时间过长,那么主UI线程会被正 在绘制的函数阻塞。那么将无法响应按键、触屏等消息。使用surfaceView ,由 于是在新的线程中更新画面所以不会阻塞UI主线程。但这也带来了另外一个问 题,就是事件同步。比如触屏了一下,需要surfaceView中 thread处理,一般就 需要有一个event queue的设计来保存touch event,这会稍稍复杂一点,因为涉 及到线程同步。所以基于以上,根据游戏特点,一般分成两类: (1 )被动更新画面的。比如棋类,这种用view就好了。因为画面的更新是依赖于 onTouch 来更新,可以直接使用 invalidate。 因为这种情况下,这一次Touch和 下一次的Touch需要的时间比较长些,不会产生影响。 (2 )主动更新。比如一个人在一直跑动。这就需要一个单独的thread不停的重绘 人的状态,避免阻塞主线程。所以显然view不合适,需要surfaceView来控制。
•
•
View的缺陷
• • View缺乏双缓冲机制 当程序需要更新View上的图像时,必须重绘View上 显示的整张图片。
SurfaceView 类
• SurfaceView是从View基类中派生出来的显示类,直接子类有 GLSurfaceView和VideoView,GL和视频播放以及Camera摄像头一般均使 用SurfaceView. SurfaceView可以控制表面的格式,比如大小、显示在屏幕中的位置,最 关键是的提供了SurfaceHolder类,使用getHolder方法获取,相关的方法 有 lockCanvas()、 lockCanvas(Rect dirty) 、 removeCallback(Callback callback)、 unlockCanvasAndPost(Canvas canvas) 控制图形以及绘制。 对于Surface,Android底层还提供了GPU加速功能,所以一般实时性很强 的应用中主要使用SurfaceView而不是直接从View 构建,同时Android后 面用到的OpenGL中的GLSurfaceView也是从该类实现。
Button btn1, btn2; SurfaceView sfv; SurfaceHolder sfh; ArrayList imglist = new ArrayList(); int imgwidth, imgheight; Bitmap bitmap; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(yout.main); btn1 = (Button) this.findViewById(R.id.btn1); btn2 = (Button) this.findViewById(R.id.btn2); btn1.setOnClickListener(new MyListener()); btn2.setOnClickListener(new MyListener()); sfv = (SurfaceView) this.findViewById(R.id.SurfaceView01); sfh = sfv.getHolder(); sfh.addCallback(new MyCallBack());// 自动运行surfaceCreated }