canvas教程

Android学习三、SurfaceView的学习(2)

字号+ 作者:H5之家 来源:H5之家 2017-10-03 15:53 我要评论( )

surfaceview变得可见时,surface被创建;surfaceview隐藏前,surface被销毁。这样能节省资源。如果你要查看 surface被创建和销毁的时机,可以重载surfaceCreated(SurfaceHolder)和 surfaceDestroyed(SurfaceHolder)

surfaceview变得可见时,surface被创建;surfaceview隐藏前,surface被销毁。这样能节省资源。如果你要查看 surface被创建和销毁的时机,可以重载surfaceCreated(SurfaceHolder)和 surfaceDestroyed(SurfaceHolder)。

surfaceview的核心在于提供了两个线程:UI线程和渲染线程。这里应注意:

1> 所有SurfaceView和SurfaceHolder.Callback的方法都应该在UI线程里调用,一般来说就是应用程序主线程。渲染线程所要访问的各种变量应该作同步处理。
2> 由于surface可能被销毁,它只在SurfaceHolder.Callback.surfaceCreated()和 SurfaceHolder.Callback.surfaceDestroyed()之间有效,所以要确保渲染线程访问的是合法有效的surface。

1、定义

可以直接从内存或者DMA等硬件接口取得图像数据,是个非常重要的绘图容器。

它的特性是:可以在主线程之外的线程中向屏幕绘图上。这样可以避免画图任务繁重的时候造成主线程阻塞,从而提高了程序的反应速度。在游戏开发中多用到SurfaceView,游戏中的背景、人物、动画等等尽量在画布canvas中画出。

2、实现

首先继承SurfaceView并实现SurfaceHolder.Callback接口
使用接口的原因:因为使用SurfaceView 有一个原则,所有的绘图工作必须得在Surface 被创建之后才能开始(Surface—表面,这个概念在图形编程中常常被提到。基本上我们可以把它当作显存的一个映射,写入到Surface 的内容
可以被直接复制到显存从而显示出来,这使得显示速度会非常快),而在Surface 被销毁之前必须结束。所以Callback 中的surfaceCreated 和surfaceDestroyed 就成了绘图处理代码的边界。

需要重写的方法

(1)publicvoidsurfaceChanged(SurfaceHolderholder,intformat,intwidth,intheight){}

  //在surface的大小发生改变时激发

 (2)publicvoidsurfaceCreated(SurfaceHolderholder){}

  //在创建时激发,一般在这里调用画图的线程。

 (3)publicvoidsurfaceDestroyed(SurfaceHolderholder){}

  //销毁时激发,一般在这里将画图的线程停止、释放。

整个过程:继承SurfaceView并实现SurfaceHolder.Callback接口 ----> SurfaceView.getHolder()获得SurfaceHolder对象 ---->SurfaceHolder.addCallback(callback)添加回调函数---->SurfaceHolder.lockCanvas()获得Canvas对象并锁定画布----> Canvas绘画
---->SurfaceHolder.unlockCanvasAndPost(Canvas canvas)结束锁定画图,并提交改变,将图形显示。

下面是SurfaceView的一个简单测试,特别提醒,最好设置SurfaceHolder.addCallBack,重写里面的方法,然后在public void surfaceCreated(SurfaceHolder holder) 里面,在再SurfaceView中画图,防止SurfaceView还没有创建好,而导致的异常。

import java.util.Timer; import java.util.TimerTask; import android.app.Activity; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.os.Bundle; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; /** * 画一个布满屏幕的格子 * */ public class SurfaceViewTest2Activity extends Activity { /** Called when the activity is first created. */ private SurfaceView surfaceView; private SurfaceHolder holder; private int screenWidth; private int screenHeight; private Timer timer; private MyTimerTask1 task1; private float currentX = 0.0f;// 记录当前的横向绘制直线的进度 private float currentY = 0.0f;// 记录当前的纵向绘制直线的进度 private Paint paint;// 画笔 private boolean reversion = false;// 控制绘制线条的反转绘制 private int countLine = 0;// 记录画的X是第几条线 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // 计算屏幕的宽高 screenWidth = getWindowManager().getDefaultDisplay().getWidth(); screenHeight = getWindowManager().getDefaultDisplay().getHeight(); // SurfaceView和holder的初始化 surfaceView = (SurfaceView) findViewById(R.id.sv); holder = surfaceView.getHolder(); holder.addCallback(new SurfaceCallBack()); // 计时器和任务的初始化 timer = new Timer(); task1 = new MyTimerTask1(); // 画笔的设置 paint = new Paint(); paint.setColor(Color.GREEN);// 画笔为绿色... paint.setStrokeWidth(2);// 设置画笔粗细 } public class SurfaceCallBack implements SurfaceHolder.Callback { public void surfaceCreated(SurfaceHolder holder) { timer.schedule(task1, 1000, 5); } public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } public void surfaceDestroyed(SurfaceHolder holder) { } } class MyTimerTask1 extends TimerTask { @Override public void run() { // 开始绘制 drawGrid(currentX, currentY); // 如果不反转的话,那么currentX++,否侧-- if (!reversion) currentX++; else currentX--; // 保持绘制x和y的同步,不过不知道为什么,在模拟器上,X到顶了,而Y没有 // 不过从输出上看,是同步的,可能是模拟器上的问题 currentY = ((float) screenHeight / screenWidth) * currentX; Log.i("test", currentX + " " + currentY); // 如果超过屏幕,那么线条就要反转,并且线条的个数要加1 if (currentX >= screenWidth) { reversion = true; countLine++; } if (currentX <= 0) { reversion = false; countLine++; } } } public void drawGrid(float x, float y) { Canvas canvas = holder.lockCanvas(new Rect(0, 0, screenWidth, screenHeight)); if (!reversion) {//没有反转的绘制情况 canvas.drawLine(0, countLine * 15, x, countLine * 15, paint); canvas.drawLine(countLine * 15, 0, countLine * 15, y, paint); } else {//反转的绘制情况 canvas.drawLine(screenWidth, countLine * 15, x, countLine * 15, paint); canvas.drawLine(countLine * 15, screenHeight, countLine * 15, y, paint); } holder.unlockCanvasAndPost(canvas); } }

参考学习的文章:点击打开链接

参考学习的文章:点击打开链接

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • android图像绘制(三)画布刷屏问题记录

    android图像绘制(三)画布刷屏问题记录

    2017-10-03 14:08

  • canvas JavaScript API学习90

    canvas JavaScript API学习90

    2017-10-02 14:00

  • canvas学习之制作动画,canvas学习动画

    canvas学习之制作动画,canvas学习动画

    2017-10-02 13:03

  • Unity3D学习笔记uGUI(9):Canvas详述

    Unity3D学习笔记uGUI(9):Canvas详述

    2017-10-02 11:06

网友点评
t