android的图像图像绘图surfacev.ppt_第1页
android的图像图像绘图surfacev.ppt_第2页
android的图像图像绘图surfacev.ppt_第3页
android的图像图像绘图surfacev.ppt_第4页
android的图像图像绘图surfacev.ppt_第5页
已阅读5页,还剩13页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

android的图像图像-SurfaceView类,2019/7/11,View和SurfaceView,View类是android的一个超类,每一个View都有一个用于绘画的画布,这个画布可以进行任意的扩展。有的时候我们需要自定义VIew实现自己想要的视图。view、SurfaceView是游戏开发中经常用到的视图。 View:显示视图,内置画布,提供图形绘制函数、触屏事件、按键事件函数等;必须在UI主线程内更新画面,速度较慢。 SurfaceView:基于view视图进行拓展的视图类,更适合2D游戏的开发;是view的子类,类似使用双缓机制,在新的线程中更新画面所以刷新界面速度比view快。,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也是从该类实现。,2019/7/11,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只在SurfaceHolder.Callback.surfaceCreated() 和 SurfaceHolder.Callback.surfaceDestroyed()调用之间是可用的,其他时间是得不到 它的Canvas对象的(null)。,Android-surfaceView 与View 的区别,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来控制。,使用SurfaceView绘制矩形,2019/7/11,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(); ,使用SurfaceView绘制矩形,2019/7/11,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绘图机制,重写CallBack对象的surfaceCreate方法,在该方法中为SurfaceView绘制背景,并避免背景图片被下一次lockCanvas遮挡。 监听触摸事件,每次触摸屏幕时,程序会锁定触碰周围的区域,那么就只更新该区域的数据,而且本次的lockCanvas会遮挡上一次的lockCanvas后绘制的图形。 注:第一次绘制的图形可能会被第二次的lockCanvas遮挡,第三次的lockcanvas又可能遮挡第二次lockCanvas的区域,但不可能遮挡第一次的lockCanvas区域,SurfaceView绘图机制,2019/7/11,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) );,SurfaceView绘图机制,2019/7/11,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的双缓冲使用,2019/7/11,前面简单介绍了SurfaceView的使用,这次就介绍SurfaceView的双缓冲使用。双缓冲是为了防止动画闪烁而实现的一种多线程应用,基于SurfaceView的双缓冲实现很简单,开一条线程并在其中绘图即可。 程序运行截图如下,左边是开单个线程读取并绘图,右边是开两个线程,一个专门读取图片,另一个专门绘图:,对比一下,右边动画的帧速明显比左边的快,左右两者都没使用Thread.sleep()。因为SurfaceView每次绘图都会锁定Canvas,也就是说同一片区域这次没画完下次就不能画,因此要提高双缓冲的效率,就得开一条线程专门画图,开另外一条线程做预处理的工作。,SurfaceView的双缓冲使用,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(R.layout.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 ,SurfaceView的双缓冲使用,class MyListener implements View.OnClickListener public void onClick(View v) if (v = btn1) new readDrawImage(0, 0).start();/ 开一条线程读取并绘图 else if (v = btn2) new readImage().start();/ 开一条线程读取 new drawImage(imgwidth + 10, 0).start();/ 开一条线程绘图 ,SurfaceView的双缓冲使用,class MyCallBack implements SurfaceHolder.Callback public void surfaceCreated(SurfaceHolder holder) Log.i(“Surface:“, “Create“); / 用反射机制来获取资源中的图片ID和尺寸 Field fields = R.drawable.class.getDeclaredFields(); for (Field field : fields) if (!“icon“.equals(field.getName()/ 除了icon之外的图片 int index = 0; try index = field.getInt(R.drawable.class); catch (IllegalArgumentException e) e.printStackTrace(); catch (IllegalAccessException e) e.printStackTrace(); / 保存图片ID imglist.add(index); / 取得图像大小 Bitmap bmImg = BitmapFactory.decodeResource(getResources(),(Integer) imglist.get(0); imgwidth = bmImg.getWidth(); imgheight = bmImg.getHeight(); ,SurfaceView的双缓冲使用,/读取并显示图片的线程 class readDrawImage extends Thread int x, y; int imgIndex = 0; public readDrawImage(int x, int y) this.x = x; this.y = y; public void run() while (true) Canvas c = sfh.lockCanvas(new Rect(this.x, this.y, this.x+ imgwidth, this.y + imgheight); Bitmap bmImg = BitmapFactory.decodeResource(getResources(),(Integer)imglist.get(imgIndex); c.drawBitmap(bmImg, this.x, this.y, new Paint(); imgIndex+; if (imgIndex = imglist.

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论