一个surfaceview 创建里面能创建两个canvas对象吗

& Surface,SurfaceView,Canvas的关系:& &
& android.view包下,public class Surface implements Parcelable{ *** }& //构造函数(可)传入SurfaceTexture对象. //Handle onto a raw buffer that is being managed by the screen compositor.
&&& public class SurfaceView extends View{ *** } //内部有mSurface变量,SurfaceHolder变量.//通过mSurfaceHolder可以获得Canvas,内部实际调用mSurface.lockCanvas()方法.
&&& public class View implements Drawable.Callback, KeyEvent.Callback,AccessibilityEventSource{ *** } //内部绘制对象的传递使用Canvas. //setFilterTouchesWhenObscured(*),安全方面使用.
&&& public interface SurfaceHolder{ *** } //Abstract interface to someone holding a display surface. //SurfaceView使用.
& android.graphics包下,public class SurfaceTexture{ *** } //Captures frames from an image stream as an OpenGL ES texture. //流可能来自照相机预览或者视频解码;
&&&&& //构造必须传入指定的OpenGLTexture的名字. //名字由GLES20.glGenTextures(*)产生.& //当指定输出为Camera,MediaPlayer时,当作SurfaceHolder使用.
&&& public class Canvas{ *** } //The Canvas class holds the &draw& calls. //内部数据通过Bitmap存储.
本文已收录于以下专栏:
相关文章推荐
转载自:http://blog.csdn.net/gophers其实每个View中都有Canvas可以用来绘制动画,只需要在这个View中重载onDraw()方法就可以,但是SurfaceView类是...
如果你是画家,有一群人想要看你的画,想象一下整个流程。
  首先找一块画布,执笔,绘制,完成后找一面墙把画挂上去,众人围观。其中不可缺少的要素包括:画布、(画家拿笔)绘制、挂墙展示。对于计算机,也就...
/android-.html
一、Surface
Surface就是“表面”的意思。在SDK的文档中...
一、Surface
Surface就是“表面”的意思。在SDK的文档中,对Surface的描述是这样的:“Handle onto a raw buffer that is being manag...
转载网址:http://blog.csdn.net/pathuang68/article/details/7351317
一、Surface
Surface就是“表面”的意思。在SDK的文档中...
一、SurfaceSurface就是“表面”的意思。在SDK的文档中,对Surface的描述是这样的:“Handle onto a raw buffer that is being managed b...
转载出处:http://blog.csdn.net/pathuang68/article/details/7351317
一、Surface
Surface就是“表面”的意思。...
一、Surface
Surface就是“表面”的意思。在SDK的文档中,对Surface的描述是这样的:“Handle onto a raw buffer that is being manag...
一、Surface
Surface就是“表面”的意思。在SDK的文档中,对Surface的描述是这样的:“Handle onto a raw buffer that is being managed...
转载请包含网址:http://blog.csdn.net/pathuang68/article/details/7351317
一、Surface
Surface就是“表面”的意思。在...
他的最新文章
讲师:汪剑
讲师:刘道宽
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)5668人阅读
Android(48)
说一下自己关于SurfaceView的一点感受:
(1.)定义:
&&& 可以直接从内存或者DMA等硬件接口取得图像数据,是个非常重要的绘图容器。
&&& 它的特性:可以在主线程之外的线程中向屏幕绘图上。这样可以避免画图任务繁重时造成主线程阻塞,从而提高了程序的反应速度。在游戏开发中多用到SurfaceView,游戏中的背景、人物、动画等等尽量在画布canvas中画出。
&& SurfaceView提供直接访问一个可画图的界面,可以控制在界面顶部的子视图层。SurfaceView是提供给需要直接画像素而不是使用窗体不见的应用使用的。Android系统中一个重要的概念和线索是Surface.View及其子类(TextView,Button等)要画在Surface上。每个Surface创建一个Canvas对象(但属性时常改变),用来管理view在Surface上的绘图操作,如画点画线,使用它是,一般都是出现在
& (2.)实现
& 首先继承SurfaceView并实现SurfaceHolder.Callback接口
& 使用接口的原因:因为使用SurfaceView有一个原则,所有的绘图工作必须得在Surface被创建之后才能开始(Surface可以当作显存的一个映射,写入到Surface的内容,可以被直接复制到显存中从而显示出来,这使得显示的速度会非常快),而在Surface被销毁之前必须结束。所以CallBack中的surfaceCreated和surfaceDestroyed就成了绘图代理代码的边界。
&& 需要重写的方法:
&& a. public void sufaceChanged(SurfaceHolder holder,int format,int width,int height){}//Surface的大小发生改变时调用
&& b. public void surfaceCreated(SurfaceHolder holder){}//Surface创建时激发,一般在这里调用画面的线程。
&& c. public void surfaceDestroyed(SurfaceHolder holder){}//销毁时激发,一般在这里将画面的线程停止、释放。
&& d. public void addCallback{};//给SurfaceView添加一个回调函数。
&& e. public void lockCanvas{};//锁定画布。绘图之前必须锁定画布才能够得到画布对象。
&& f. public void unlockCanvasAndPost{};//开始绘制时锁定了画布,绘制完成后解锁画布。
&& g. public void removeCallback:从SurfaceView中移除回调函数。
& SurfaceView不同View之处在于,SurfaceView不需要通过线程来更新视图,但是再绘制前需要使用locakCanvas锁定画布,并且得到画布,然后再画布上绘制你需要的图像。绘制完成后需要使用lockCanvasAndPost方法来解锁画布。于是才能显示在屏幕上。事件的处理规则和View是一样的。
&整个实现过程:
继承SurfaceView并实现SurfaceHolder.Callback接口------&SurfaceView.getHolder()获得SurfaceHolder对象-----&SurfaceHolder.addCallback(callback)添加回调函数-----&
& surfaceHolder.lockCanvas()获得Canvas对象并锁定画布------&Canvas绘画-------&SurfaceHolder.unlockCanvasAndPost(Canvas canvas)结束锁定画图,并提交改变,将图形显示。
&(3.)SurfaceHolder:
&& 这里用到了一个类SurfaceHolder,可以把它当成surface的控制器,用来操纵surface。处理它的Canvas上画的效果和动画,控制表面,大小,像素等。
&& 几个常用的方法:
&& a.abstract void addCallback(SurfaceHolder.Callbask callback);//给SurfaceView当前的持有者一个回调函数。
&& b.abstract Canvas lockCanvas();//锁定画布,一般在锁定后就可以通过其返回的画布对象Canvas,在其上面等操纵了。
&& c.abstract Canvas lockCanvas(Rect dirty);//锁定画布的某个区域进行画图等..因为画完图后,会调用下面的unlockCanvasAndPost()来改变显示的内容。相对部分内存要求比较高的游戏来说,&&可以不用重画dirty外的其他区域的像素,可以提高速度。
&& d.abstract void unlockCanvasAndPost(Canvas canvas);//结束锁定画图,并提交改变。&
& 最后通过一个SurfaceView开发一个示波器的例子,来结束SurfaceView吧(代码太多,放在下一篇博文中),谢谢
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:402873次
积分:3808
积分:3808
排名:第10237名
原创:63篇
转载:25篇
评论:68条
(1)(1)(3)(1)(4)(4)(10)(21)(10)(9)(4)(4)(5)(2)(9)
(window.slotbydup = window.slotbydup || []).push({
id: '4740881',
container: s,
size: '200,200',
display: 'inlay-fix'程序写累了,就来玩玩酷跑小游戏吧,嘿嘿。
雨松MOMO送你一首歌曲,嘿嘿。
Android研究院之游戏开发View与SurFaceView的区别(五)
Android研究院之游戏开发View与SurFaceView的区别(五)
围观15397次
编辑日期: 字体:
view在api中的结构
java.lang.Object
android.view.View
直接子类:
AnalogClock, ImageView, KeyboardView, ProgressBar, SurfaceView, TextVie, ViewGroup, ViewStub
间接子类:
AbsListView, AbsSeekBar, AbsSpinner, AbsoluteLayout, AdapterView&T extends Adapter&, AppWidgetHostView, AutoCompleteTextView, Button, CheckBox, CheckedTextView, Chronometer, CompoundButton, DatePicker, DialerFilter, DigitalClock,EditView, ExpandableListView, ExtractEditText, FrameLayout, GLSurfaceView, Gallery, GestureOverlayView, GridView, HorizontalScrollView, ImageButton, ImageSwitcher, LinearLayout, ListView, MediaController, MultiAutoCompleteTextView, QuickContactBadge, RadioButton, RadioGroup, RatingBar, RelativeLayout, ScrollView, SeekBar, SlidingDrawer, Spinner, TabHost, TabWidget, TableLayout, TableRow, TextSwitcher, TimePicker, ToggleButton, TwoLineListItem, VideoView, ViewAnimator, ViewFlipper, ViewSwitcher, WebView, ZoomButton, ZoomControls
由此可见View类属于Android开发绘制中的显示老大,任何与绘制有关系的控件都是它的子类。在这篇文章中我主要讲View 与SurFaceView 使用线程刷新屏幕绘制方面的知识。开发中如何去选择使用View还是SurFaceView。我相信读过我前几篇博客的朋友应该知道我在刷新屏幕的时候使用invalidate()方法来重绘,下面我详细的说明一下Andooid刷新屏幕的几种方法。
第一种: 在onDraw方法最后调用invalidate()方法,它会通知UI线程重绘 这样 View会重新调用onDraw方法,实现刷新屏幕。 这样写看起来代码非常简洁漂亮,但是它也同时存在一个很大的问题,它和游戏主线程是分开的 它违背了单线程模式,这样操作绘制的话是很不安全的,举个例子 比如程序先进在Activity1中 使用invalidate()方法来重绘, 然后我跳到了Activity2这时候Activity1已经finash()掉 可是Activity1中 的invalidate() 的线程还在程序中,Android的虚拟机不可能主动杀死正在运行中的线程所以这样操作是非常危险的。因为它是在UI线程中被动掉用的所以很不安全。
invalidate()
更新整个屏幕区域
invalidate(Rect rect) 更新Rect区域
invalidate(l, t, r, b) 更新指定矩形区域
&&&&public void onDraw(Canvas canvas){&&&&&&&&&&&&DosomeThing();&&&&&&&&&&&&invalidate();&&&&}
第二种:使用postInvalidate();方法来刷新屏幕 ,调用后它会用handler通知UI线程重绘屏幕,我们可以 new
Thread(this).start(); 开启一个游戏的主线程 然后在主线程中通过调用postInvalidate();方法来刷新屏幕。postInvalidate();方法 调用后 系统会帮我们调用onDraw方法 ,它是在我们自己的线程中调用 通过调用它可以通知UI线程刷新屏幕 。由此可见它是主动调用UI线程的。所以建议使用postInvalidate()方法通知UI线程来刷新整个屏幕。
postInvalidate(left, top, right, bottom) 方法 通过UI线程来刷新规定矩形区域。
123456789101112
@Override public void run() { &&&&while (mIsRunning) {
&&&&Thread.sleep(100);&&&&&&&&&&&&&&&&&&&&postInvalidate();
} catch (InterruptedException e) {
&&&&// TODO Auto-generated catch block
&&&&e.printStackTrace();
View中用到的双缓冲技术
重绘的原理是 程序根据时间来刷新屏幕 如果有一帧图形还没有完全绘制结束 程序就开始刷新屏幕这样就会造成瞬间屏幕闪烁 画面很不美观,所以双缓冲的技术就诞生了。它存在的目的就是解决屏幕闪烁的问题,下面我说说在自定义View中如何实现双缓冲。
首先我们需要创建一张屏幕大小的缓冲图片,我说一下第三个参数 ARGB 分别代表的是 透明度
Bitmap.Config
分别占四位
Bitmap.Config
分别占八位
Bitmap.Config
没有透明度(A)
一般情况下我们使用ARGB_8888 因为它的效果是最好了 当然它也是最占内存的。
&& mBufferBitmap = Bitmap.createBitmap(mScreenWidth,mScreenHeight,Config.ARGB_8888);
创建一个缓冲的画布,将内容绘制在缓冲区mBufferBitmap中
Canvas mCanvas = new Canvas(); mCanvas.setBitmap(mBufferBitmap);
最后一次性的把缓冲区mBufferBitmap绘制在屏幕上,怎么样 简单吧 呵呵。
12345678910111213141516171819202122232425
@Override protected void onDraw(Canvas canvas) { &&&&/**这里先把所有须要绘制的资源绘制到mBufferBitmap上**/ &&&&/**绘制地图**/ &&&&DrawMap(mCanvas,mPaint,mBitmap); &&&&/**绘制动画**/ &&&&RenderAnimation(mCanvas); &&&&/**更新动画**/ &&&&UpdateAnimation();& &&&&if(isBorderCollision) {
DrawCollision(mCanvas,"与边界发生碰撞"); &&&&}& &&&&if(isAcotrCollision) {
DrawCollision(mCanvas,"与实体层发生碰撞"); &&&&} &&&&if(isPersonCollision) {
DrawCollision(mCanvas,"与NPC发生碰撞"); &&&&}& &&&&/**最后通过canvas一次性的把mBufferBitmap绘制到屏幕上**/ &&&&canvas.drawBitmap(mBufferBitmap, 0,0, mPaint); &&&&super.onDraw(canvas); }
由此可见view属于被动刷新, 因为我们做的任何刷新的操作实际上都是通知UI线程去刷新。所以在做一些只有通过玩家操作以后才会刷新屏幕的游戏 并非自动刷新的游戏 可以使用view来操作。
2.SurfaceView
从API中可以看出SurfaceView属于View的子类 它是专门为制作游戏而产生的,它的功能非常强大,最重要的是它支持OpenGL ES库,2D和3D的效果都可以实现。创建SurfaceView的时候需要实现SurfaceHolder.Callback接口,它可以用来监听SurfaceView的状态,SurfaceView的改变 SurfaceView的创建 SurfaceView 销毁
我们可以在相应的方法中做一些比如初始化的操作 或者 清空的操作等等。
使用SurfaceView构建游戏框架它的绘制原理是绘制前先锁定画布 然后等都绘制结束以后 在对画布进行解锁 最后在把画布内容显示到屏幕上。
代码中是如何实现SurfaceView
首先需要实现 Callback 接口 与Runnable接口
public class AnimView extends SurfaceView implements Callback,Runnable
获取当前mSurfaceHolder 并且把它加到CallBack回调函数中
&&&&SurfaceHolder&&mSurfaceHolder = getHolder(); &&&&mSurfaceHolder.addCallback(this);
通过callBack接口监听SurfaceView的状态, 在它被创建的时候开启游戏的主线程,结束的时候销毁。这里说一下在View的构造函数中是拿不到view有关的任何信息的,因为它还没有构建好。 所以通过这个监听我们可以在surfaceCreated()中拿到当前view的属性 比如view的宽高 等等,所以callBack接口还是非常有用处的。
1234567891011121314151617181920
@Override public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2,
int arg3) { &&&&// surfaceView的大小发生改变的时候& }& @Override public void surfaceCreated(SurfaceHolder arg0) { &&&&/**启动游戏主线程**/ &&&&mIsRunning = true; &&&&mThread = new Thread(this); &&&&mThread.start(); }& @Override public void surfaceDestroyed(SurfaceHolder arg0) {
// surfaceView销毁的时候 &&&&mIsRunning = false; }
在游戏主线程循环中在绘制开始 先拿到画布canvas 并使用mSurfaceHolder.lockCanvas()锁定画布,等绘制结束以后 使用mSurfaceHolder.unlockCanvasAndPost(mCanvas)解锁画布,
解锁画布以后画布上的内容才会显示到屏幕上。
1234567891011121314151617181920
@Override public void run() { &&&&while (mIsRunning) {
&&&&Thread.sleep(100);
} catch (InterruptedException e) {
&&&&// TODO Auto-generated catch block
&&&&e.printStackTrace();
//在这里加上线程安全锁
synchronized (mSurfaceHolder) {
&&&&/**拿到当前画布 然后锁定**/
&&&&mCanvas =mSurfaceHolder.lockCanvas();
&&&&Draw();
&&&&/**绘制结束后解锁显示在屏幕上**/
&&&&mSurfaceHolder.unlockCanvasAndPost(mCanvas);
由此可见SurfaceView 属于主动刷新 ,重绘过程完全是在我们自己的线程中完成 , 由于游戏中肯定会执行各种绚丽的动画效果如果使用被动刷新的View就有可能就会阻塞UI线程,所以SurfaceView 更适合做游戏。
最近有朋友反映说运行起来有点卡 我解释一下,
卡的主要原因是我的地图文件太大了,当然还有模拟器不给力的原因。我每绘制一块地图就须要使用裁剪原图,频繁的切割如此大的图片肯定会造成卡顿的情况。同学们在制作的时候将没用的地图块去掉,保留只需要的地图块这样会流畅很多喔 。
优化游戏主线程循环
同学们先看看这段代码,Draw()方法绘制结束让线程等待100毫秒在进入下一次循环。其实这样更新游戏循环是很不科学的,原因是Draw()方法每一次更新所耗费的时间是不确定的。举个例子 比如第一次循环Draw() 耗费了1000毫秒 加上线程等待100毫秒 整个循环耗时1100毫秒,第二次循环Draw() 耗时2000毫秒 加上线程等待时间100毫秒 整个循环时间就是2100毫秒。很明显这样就会造成游戏运行刷新时间时快时慢,所以说它是很不科学的。
1234567891011121314151617
public void run() { &&&&while (mIsRunning) {
//在这里加上线程安全锁
synchronized (mSurfaceHolder) {
&&&&/**拿到当前画布 然后锁定**/
&&&&mCanvas =mSurfaceHolder.lockCanvas();
&&&&Draw();
&&&&/**绘制结束后解锁显示在屏幕上**/
&&&&mSurfaceHolder.unlockCanvasAndPost(mCanvas);
&&&&Thread.sleep(100);
} catch (InterruptedException e) {
&&&&e.printStackTrace();
在贴一段科学的控游戏制循环代码,每次循环游戏主线程 在Draw()方法前后计算出Draw()方法所消耗的时间,然后在判断是否达到我们规定的刷新屏幕时间,下例是以30帧刷新一次屏幕,如果满足则继续下次循环如果不满足使用Thread.yield(); 让游戏主线程去等待 并计算当前等待时间直到等待时间满足30帧为止在继续下一次循环刷新游戏屏幕。
这里说一下Thread.yield(): 与Thread.sleep(long millis):的区别,Thread.yield(): 是暂停当前正在执行的线程对象 ,并去执行其他线程。Thread.sleep(long millis):则是使当前线程暂停参数中所指定的毫秒数然后在继续执行线程。
123456789101112131415161718192021222324252627282930313233
&&&&&&&&/**每30帧刷新一次屏幕**/&&&&&&&&public static final int TIME_IN_FRAME = 30; @Override public void run() { &&&&while (mIsRunning) {&
/**取得更新游戏之前的时间**/
long startTime = System.currentTimeMillis();&
/**在这里加上线程安全锁**/
synchronized (mSurfaceHolder) {
&&&&/**拿到当前画布 然后锁定**/
&&&&mCanvas =mSurfaceHolder.lockCanvas();
&&&&Draw();
&&&&/**绘制结束后解锁显示在屏幕上**/
&&&&mSurfaceHolder.unlockCanvasAndPost(mCanvas);
/**取得更新游戏结束的时间**/
long endTime = System.currentTimeMillis();&
/**计算出游戏一次更新的毫秒数**/
int diffTime&&= (int)(endTime - startTime);&
/**确保每次更新时间为30帧**/
while(diffTime &=TIME_IN_FRAME) {
&&&&diffTime = (int)(System.currentTimeMillis() - startTime);
&&&&/**线程等待**/
&&&&Thread.yield();
}& &&&&} }
最后由于代码较多我就不贴在博客中了 , 下面给出Demo源码的下载地址欢迎大家下载阅读互相学习,互相研究,互相讨论 雨松MOMO希望可以和大家一起进步。
下载地址:
本文固定链接:
转载请注明:
雨松MOMO提醒您:亲,如果您觉得本文不错,快快将这篇文章分享出去吧 。另外请点击网站顶部彩色广告或者捐赠支持本站发展,谢谢!
作者:雨松MOMO
专注移动互联网,Unity3D游戏开发
如果您愿意花10块钱请我喝一杯咖啡的话,请用手机扫描二维码即可通过支付宝直接向我捐款哦。
您可能还会对这些文章感兴趣!8856人阅读
使用双surface,将第一个设置为透明背景,在摄像机上绘制图像,纠结搞了一天。
其中参考了http://blog.csdn.net/yanzi1225627/article/details/7934710 的思路和代码,但是,始终会出现 canvas=holder.lockcanvas();返回的canvas为null的情况。加入线程后解决问题。
主Activity:
public class MainActivity extends Activity {
private SVDraw surfaceDraw =
private SurfaceView surfaceView =
private SurfaceHolder holder1 =
private Canvas canvas =
private Camera cam =
private boolean previewRunning =
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//绘制surface1
surfaceView = (SurfaceView) findViewById(R.id.surface1);
holder1 = surfaceView.getHolder();
holder1.addCallback(new MySurfaceViewCallback());
holder1.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
holder1.setFixedSize(500, 350);
holder1.setFormat(PixelFormat.TRANSPARENT);
canvas = holder1.lockCanvas();
if (canvas != null) {
canvas.drawColor(Color.TRANSPARENT);
Paint p = new Paint();
p.setAntiAlias(true);
p.setColor(Color.RED);
p.setStyle(Style.STROKE);
// canvas.drawPoint(100.0f, 100.0f, p);
canvas.drawLine(0, 110, 500, 110, p);
// 绘制surface2
其中使用线程
surfaceDraw = (SVDraw) findViewById(R.id.mDraw);
surfaceDraw.setVisibility(View.VISIBLE);
surfaceDraw.drawLine();
// =============================create surface 1=================================================
private class MySurfaceViewCallback implements SurfaceHolder.Callback {
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
@SuppressWarnings(&deprecation&)
public void surfaceCreated(SurfaceHolder holder) {
cam = Camera.open(); // 取得第一个摄像头
Parameters param = cam.getParameters();
// param.setPreviewSize(display.getWidth(), display.getHeight()) ;
param.setPreviewFrameRate(5); // 一秒5帧
param.setPictureFormat(PixelFormat.JPEG); // 图片形式
param.set(&jpen-quality&, 80);
cam.setParameters(param);
cam.setDisplayOrientation(90); // 纠正摄像头自动旋转,纠正角度,如果引用,则摄像角度偏差90度
cam.setPreviewDisplay(holder);
} catch (IOException e) {
cam.startPreview(); // 进行预览
previewRunning = // 已经开始预览
public void surfaceDestroyed(SurfaceHolder holder) {
if (cam != null) {
if (previewRunning) {
cam.stopPreview(); // 停止预览
previewRunning =
cam.release();
/*只不过一个是继承的view一个是surfaceview,将AttributeSetattrs加上。只要处理好谁是顶层的view谁设成透明,预览视频的surfaceview设成底层,在且要在xml属性文件里设成visible就可以了*/
public class SVDraw extends SurfaceView implements SurfaceHolder.Callback{
protected SurfaceH
private int mW
private int mH
private MyT
public SVDraw(Context context, AttributeSet attrs) {
super(context, attrs);
sh = this.getHolder();
sh.addCallback(this);
sh.setFormat(PixelFormat.TRANSPARENT);
setZOrderOnTop(true);
public void surfaceChanged(SurfaceHolder arg0, int arg1, int w, int h) {
public void surfaceCreated(SurfaceHolder arg0) {
public void surfaceDestroyed(SurfaceHolder arg0) {
void clearDraw()
Canvas canvas = sh.lockCanvas();
canvas.drawColor(Color.BLUE);
sh.unlockCanvasAndPost(canvas);
public void drawLine()
//预览视频的时候绘制图像
/*Canvas canvas = sh.lockCanvas();
canvas.drawColor(Color.TRANSPARENT);
Paint p = new Paint();
p.setAntiAlias(true);
p.setColor(Color.RED);
p.setStyle(Style.STROKE);
//canvas.drawPoint(100.0f, 100.0f, p);
canvas.drawLine(0,110, 500, 110, p);
canvas.drawCircle(110, 110, 10.0f, p);
sh.unlockCanvasAndPost(canvas);*/
thread = new MyThread(sh);
thread.setRun(true);
thread.start();
// 绘制线程
public class MyThread extends Thread {
private SurfaceH
public MyThread(SurfaceHolder holder) {
this.holder =
public void run() {
int counter = 0;
Canvas canvas =
while (run) {
// 具体绘制工作
// 获取Canvas对象,并锁定之
canvas = holder.lockCanvas();
// 设定Canvas对象的背景颜色
canvas.drawColor(Color.TRANSPARENT);
// 创建画笔
Paint p = new Paint();
// 设置画笔颜色
p.setColor(Color.RED);
// 设置文字大小
p.setTextSize(30);
// 创建一个Rect对象rect
Rect rect = new Rect(100, 50, 380, 330);
// 在canvas上绘制rect
canvas.drawRect(rect, p);
// 在canvas上显示时间
canvas.drawText(&Interval = & + (counter++) + & seconds.&, 100, 410, p);
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (canvas != null) {
// 解除锁定,并提交修改内容
holder.unlockCanvasAndPost(canvas);
public boolean isRun() {
public void setRun(boolean run) {
this.run =
&?xml version=&1.0& encoding=&utf-8&?&
&manifest xmlns:android=&/apk/res/android&
package=&com.example.test02&
android:versionCode=&1&
android:versionName=&1.0& &
android:minSdkVersion=&8&
android:targetSdkVersion=&18& /&
&application
android:allowBackup=&true&
android:icon=&@drawable/ic_launcher&
android:label=&@string/app_name&
android:theme=&@style/AppTheme& &
android:name=&com.example.test02.MainActivity&
android:label=&@string/app_name& &
&intent-filter&
&action android:name=&android.intent.action.MAIN& /&
&category android:name=&android.intent.category.LAUNCHER& /&
&/intent-filter&
&/activity&
&/application&
&&uses-feature android:name=&android.hardware.camera& /&
&uses-feature android:name=&android.hardware.camera.autofocus& /&
&uses-permission android:name=&android.permission.CAMERA& /&
&uses-permission android:name=&android.permission.MOUNT_UNMOUNT_FILESYSTEMS& /&
&uses-permission android:name=&android.permission.WRITE_EXTERNAL_STORAGE& /&
&/manifest&
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:103210次
积分:1233
积分:1233
排名:千里之外
原创:21篇
转载:12篇
评论:32条
(1)(1)(3)(2)(1)(4)(3)(7)(1)(2)(1)(2)(1)(1)(2)(1)
(window.slotbydup = window.slotbydup || []).push({
id: '4740881',
container: s,
size: '200,200',
display: 'inlay-fix'

我要回帖

更多关于 动态创建 surfaceview 的文章

 

随机推荐