`

Android中SurfaceView的使用示例

阅读更多

SurfaceView在游戏开发中有着举足轻重的地位,它对于画面的控制有着更大的自由度(不像View要用handler来更新,关于View的),但这方面的参考资料并不是太多,能找到的例子都有点喧宾夺主的感觉,不能把使用的流程清晰展示出来,下面是个简单的示例,力求把流程清楚展示,其他的可简则简。

 

程序效果:用线程画一个蓝色的长方形。

package com.ray.test;
/*
 * SurfaceView的示例程序
 * 演示其流程
 */
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class Test extends Activity {
    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 = this.getHolder();//获取holder
			holder.addCallback(this);
			//setFocusable(true);
			
		}

		@Override
		public void surfaceChanged(SurfaceHolder holder, int format, int width,
				int height) {
			
		}

		@Override
		public void surfaceCreated(SurfaceHolder holder) {
			new Thread(new MyThread()).start();
		}

		@Override
		public void surfaceDestroyed(SurfaceHolder holder) {
			
		}
		
		//内部类的内部类
		class MyThread implements Runnable{

			@Override
			public void run() {
				Canvas canvas = holder.lockCanvas(null);//获取画布
				Paint mPaint = new Paint();
				mPaint.setColor(Color.BLUE);
				
				canvas.drawRect(new RectF(40,60,80,80), mPaint);
				holder.unlockCanvasAndPost(canvas);//解锁画布,提交画好的图像
				
			}
			
		}
    	
    }
}

 

分享到:
评论
14 楼 liangxping 2013-09-03  
就是双缓存机制而已。
13 楼 bq49 2010-06-29  
raymondlueng 写道
ansili 写道
那如果我想在上次画的基础上接着画呢?。
  也就是说我第一次在surfaceview 画了一个方块,再次接到用户的动作时在上次所画结果上接着在surfaceview 再画一个方块.此时surfaceview 上已经存在两个方块了。
   surfaceview  能否胜任? 需要怎么做?

如果要保留当前的接着画,SurfaceView是无法做到的!


=============应该是可以的!SurfaceView绘制无非也就是用的Canvas,只要获得了这个Canvas就可以画了!这个效果应该就是差不多的例子吧!
http://sean.huanglijiang.com/article.asp?id=227
12 楼 nsm1168 2009-12-16  
可以看看这里的介绍 如何在surfaceview里实现有停頓的計時性繪圖!
http://android.tgbus.com/Android/tutorial/200812/171431.shtml
11 楼 brumby007 2009-10-21  
期待答案中……,同样顶一个
10 楼 jjcang 2009-10-21  
这个不错,顶一个
9 楼 brumby007 2009-10-11  
谢谢楼上大哥的回复,可是不知道为什么在lunarlander里面是这样实现的,也没有做sleep,我看logcat打出来的东西是一直在狂刷的:
        public void run() {
            while (mRun) {
                Canvas c = null;
                try {
                    c = mSurfaceHolder.lockCanvas(null);
                    synchronized (mSurfaceHolder) {
                        if (mMode == STATE_RUNNING) updatePhysics();
                        Log.d("test", ">>>>>>>>>>>>dodraw");
                        doDraw(c);
                    }
                } finally {
                    // do this in a finally so that if an exception is thrown
                    // during the above, we don't leave the Surface in an
                    // inconsistent state
                    if (c != null) {
                        mSurfaceHolder.unlockCanvasAndPost(c);
                    }
                }
            }
        }

而且如果我用sleep的话,物体移动会有明显卡住的感觉。不知道是怎么回事?
小弟初学,还请赐教
8 楼 vlinux 2009-10-11  
brumby007 写道
我明白了,更新画面时不用sleep,看LunarLander的例子里更新UI的线程也是一直狂跑的,占满了一个CPU


你错了,如果你不sleep而狂刷,你会发现不仅你的短信、电话等后台程序工作缓慢,而且你还能看到如下的警告信息

引用
10-11 13:20:01.534: WARN/SurfaceComposerClient(1938): lock_layer timed out (is the CPU pegged?) layer=1, lcblk=0x424d00a0, state=00000011 (was 00000012)
10-11 13:20:01.534: WARN/SurfaceFlinger(99): executeScheduledBroadcasts() skipped, contention on the client. We'll try again later...
10-11 13:20:01.534: WARN/SurfaceComposerClient(1938): lock_layer() timed out but didn't appear to need to be locked and we recovered (layer=1, lcblk=0x424d00a0, state=00000001)


所以,在lock之外sleep是非常必要滴
7 楼 brumby007 2009-10-11  
我明白了,更新画面时不用sleep,看LunarLander的例子里更新UI的线程也是一直狂跑的,占满了一个CPU
6 楼 brumby007 2009-09-22  
<div class="quote_title">raymondlueng 写道</div>
<div class="quote_div">
<p>SurfaceView在游戏开发中有着举足轻重的地位,它对于画面的控制有着更大的自由度(<a title="利用Handler来更新Android UI" href="/blog/411860" target="_blank">不像View要用handler来更新,关于View的</a>),但这方面的参考资料并不是太多,能找到的例子都有点喧宾夺主的感觉,不能把使用的流程清晰展示出来,下面是个简单的示例,力求把流程清楚展示,其他的可简则简。</p>
<p> </p>
<p>程序效果:用线程画一个蓝色的长方形。</p>
<pre name="code" class="java">package com.ray.test;
/*
* SurfaceView的示例程序
* 演示其流程
*/
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class Test extends Activity {
    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 = this.getHolder();//获取holder
holder.addCallback(this);
//setFocusable(true);

}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {

}

@Override
public void surfaceCreated(SurfaceHolder holder) {
new Thread(new MyThread()).start();
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {

}

//内部类的内部类
class MyThread implements Runnable{

@Override
public void run() {
Canvas canvas = holder.lockCanvas(null);//获取画布
Paint mPaint = new Paint();
mPaint.setColor(Color.BLUE);

canvas.drawRect(new RectF(40,60,80,80), mPaint);
holder.unlockCanvasAndPost(canvas);//解锁画布,提交画好的图像

}

}
   
    }
}</pre>
<p> </p>
</div>
<p>根据楼主的demo我也写了个小小的demo,可就是物体移动的时候比较慢,不知道是为什么?</p>
<pre name="code" class="java">package com.mcgk.paopao;

import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import com.mcgk.paopao.Paopao.MyView.MyThread;
import com.mcgk.util.BackgroundUtil;

public class Paopao extends Activity {
private MyThread mythread;
private static boolean drawFlag = false;
private static int x = 14;
private static int y = 20;

/** Called when the activity is first created. */
@Override
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 = this.getHolder();// 获取holder
holder.addCallback(this);
setFocusable(true);

}

@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
Resources r = this.getContext().getResources();
BackgroundUtil.drawBackground(r, canvas);
BackgroundUtil.drawTree(r, canvas, x, y);
drawFlag = true;
}

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
return mythread.onKeyDown(keyCode, event);
}

@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
return mythread.onKeyUp(keyCode, event);
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {

}

@Override
public void surfaceCreated(SurfaceHolder holder) {
mythread = new MyThread(holder, this);
new Thread(mythread).start();
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {

}

class MyThread implements Runnable {
private SurfaceHolder holder;
private MyView _panel; 
public MyThread(SurfaceHolder holder, MyView panel) {
this.holder = holder;
this._panel = panel;
}

public boolean onKeyUp(int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
return false;
}

public boolean onKeyDown(int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
synchronized (holder) {
if (keyCode == KeyEvent.KEYCODE_DPAD_UP){
y = y - 30;
}else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN){
y = y + 30;
}else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT){
x = x - 30;
}else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT){
x = x + 30;
}
}
drawFlag = false;
return false;
}

@Override
public void run() {
Canvas c;
while (true) {
c = null;
if(drawFlag){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
continue;
}
try {
c = holder.lockCanvas(null);
synchronized (holder) {
_panel.onDraw(c);
}
} finally {
if (c != null) {
holder.unlockCanvasAndPost(c);
}
}

}

}

}
}</pre>
 
5 楼 christensen 2009-09-20  
每次画2个方块
4 楼 raymondlueng 2009-09-18  
ansili 写道
那如果我想在上次画的基础上接着画呢?。
  也就是说我第一次在surfaceview 画了一个方块,再次接到用户的动作时在上次所画结果上接着在surfaceview 再画一个方块.此时surfaceview 上已经存在两个方块了。
   surfaceview  能否胜任? 需要怎么做?

如果要保留当前的接着画,SurfaceView是无法做到的!
3 楼 ansili 2009-09-18  
那如果我想在上次画的基础上接着画呢?。
  也就是说我第一次在surfaceview 画了一个方块,再次接到用户的动作时在上次所画结果上接着在surfaceview 再画一个方块.此时surfaceview 上已经存在两个方块了。
   surfaceview  能否胜任? 需要怎么做?
2 楼 raymondlueng 2009-09-18  
ansili 写道
在用SurfaceView时遇到问题请指点.
每次把画当前正方形时,把上次的清除掉,现在显示很乱画图代码如下
  
	public void selectSmallPicture(Point _origialPoint)
	{
		
		if(_origialPoint == null)
		{
			return ;
		}
		
		Canvas canvas = holder.lockCanvas();// 获取画布
		
		int startX =  _origialPoint.x * (PICTURE_EXTENT + CUBICLE) - 1;
		int startY =  _origialPoint.y * (PICTURE_EXTENT + CUBICLE) - 1;
		//canvas.save();
		
		Paint linePaint = new Paint();
		linePaint.setColor(Color.RED);
		canvas.drawLine(startX, startY,  startX , startY + PICTURE_EXTENT, linePaint);
		canvas.drawLine(startX, startY,  startX + PICTURE_EXTENT, startY , linePaint);
		canvas.drawLine(startX+ PICTURE_EXTENT, startY,  startX + PICTURE_EXTENT, startY + PICTURE_EXTENT, linePaint);
		canvas.drawLine(startX, startY + PICTURE_EXTENT,  startX + PICTURE_EXTENT, startY + PICTURE_EXTENT, linePaint);
		
		if(tempPoint!=null)
		{
			startX =  tempPoint.x * (PICTURE_EXTENT + CUBICLE) - 1;
			startY =  tempPoint.y * (PICTURE_EXTENT + CUBICLE) - 1;
			linePaint.setColor(bgcolor);
			canvas.drawLine(startX, startY,  startX , startY + PICTURE_EXTENT, linePaint);
			canvas.drawLine(startX, startY,  startX + PICTURE_EXTENT, startY , linePaint);
			canvas.drawLine(startX+ PICTURE_EXTENT, startY,  startX + PICTURE_EXTENT, startY + PICTURE_EXTENT, linePaint);
			canvas.drawLine(startX, startY + PICTURE_EXTENT,  startX + PICTURE_EXTENT, startY + PICTURE_EXTENT, linePaint);
		}
		

		canvas.restore();
		holder.unlockCanvasAndPost(canvas);// 解锁画布,提交画好的图像
		tempPoint  = _origialPoint;
	}





Android surfaceview 的画图机制是这样设计的,只能画一次背景,再画你想画的才可以!
1 楼 ansili 2009-09-18  
在用SurfaceView时遇到问题请指点.
每次把画当前正方形时,把上次的清除掉,现在显示很乱画图代码如下
  
	public void selectSmallPicture(Point _origialPoint)
	{
		
		if(_origialPoint == null)
		{
			return ;
		}
		
		Canvas canvas = holder.lockCanvas();// 获取画布
		
		int startX =  _origialPoint.x * (PICTURE_EXTENT + CUBICLE) - 1;
		int startY =  _origialPoint.y * (PICTURE_EXTENT + CUBICLE) - 1;
		//canvas.save();
		
		Paint linePaint = new Paint();
		linePaint.setColor(Color.RED);
		canvas.drawLine(startX, startY,  startX , startY + PICTURE_EXTENT, linePaint);
		canvas.drawLine(startX, startY,  startX + PICTURE_EXTENT, startY , linePaint);
		canvas.drawLine(startX+ PICTURE_EXTENT, startY,  startX + PICTURE_EXTENT, startY + PICTURE_EXTENT, linePaint);
		canvas.drawLine(startX, startY + PICTURE_EXTENT,  startX + PICTURE_EXTENT, startY + PICTURE_EXTENT, linePaint);
		
		if(tempPoint!=null)
		{
			startX =  tempPoint.x * (PICTURE_EXTENT + CUBICLE) - 1;
			startY =  tempPoint.y * (PICTURE_EXTENT + CUBICLE) - 1;
			linePaint.setColor(bgcolor);
			canvas.drawLine(startX, startY,  startX , startY + PICTURE_EXTENT, linePaint);
			canvas.drawLine(startX, startY,  startX + PICTURE_EXTENT, startY , linePaint);
			canvas.drawLine(startX+ PICTURE_EXTENT, startY,  startX + PICTURE_EXTENT, startY + PICTURE_EXTENT, linePaint);
			canvas.drawLine(startX, startY + PICTURE_EXTENT,  startX + PICTURE_EXTENT, startY + PICTURE_EXTENT, linePaint);
		}
		

		canvas.restore();
		holder.unlockCanvasAndPost(canvas);// 解锁画布,提交画好的图像
		tempPoint  = _origialPoint;
	}




相关推荐

    Android中SurfaceView截屏

    在Android开发中,`SurfaceView`是一个非常重要的视图组件,尤其在处理视频播放、游戏渲染等高性能图形操作时,它的优势在于拥有独立于主线程的渲染机制,能避免阻塞UI更新。然而,由于其特殊的性质,直接通过常规...

    android之surfaceview学习示例

    在这个"android之surfaceview学习示例"中,我们将深入探讨SurfaceView的核心特性和使用方法。 首先,SurfaceView拥有自己的Surface对象,它位于窗口的最底层,直接与硬件交互,允许在主线程之外进行绘制操作,避免...

    android surfaceview示例源码下载

    android中的surfaceview示例源码下载,Android SurfaceView在游戏开发中使用想当广泛,SurfaceView对于画面的控制有着更大的自由度,它不像View那样要用handler来更新,但是网上关于 SurfaceView使用这方面的参考...

    android SurfaceView 使用示例 why SurfaceView上 不可以用控件的轻微解释

    在Android开发中,SurfaceView是一种特殊的视图组件,它提供了与硬件图形渲染引擎直接交互的能力,常用于处理高性能、低延迟的视频或者游戏画面。SurfaceView的底层机制使其能够独立于UI主线程进行渲染,避免了频繁...

    Android圆形相机预览窗口,圆形SurfaceView

    在Android开发中,有时我们可能需要创建一个独特的用户体验,比如设计一个圆形的相机预览窗口。这个场景就涉及到了Android的SurfaceView以及如何定制它的显示效果。本文将深入探讨如何实现一个圆形的相机预览窗口。 ...

    android surfaceView 双缓冲

    android使用双缓冲辨析及surfaceview使用例子

    Android SurfaceView使用Demo

    总之,`SurfaceView` 是 Android 应用开发中用于实现高性能图形渲染的重要工具,理解其工作原理和使用方式对于开发高质量、流畅的应用至关重要。在实际项目中,根据需求选择合适的视图组件,能够有效提升用户体验。

    Android下使用SurfaceView播放视频文件

    本篇文章将深入探讨如何在Android应用中使用SurfaceView来播放视频文件。 首先,我们需要了解SurfaceView的核心组件: 1. **Surface**: 这是SurfaceView内部的一个特殊缓冲区,用于渲染图像。当视频播放器(如...

    android之surfaceview游戏开发

    文件"example_surfaceview2"可能包含了使用SurfaceView进行游戏开发的示例代码,包括SurfaceHolder的回调函数实现、游戏循环的编写、触摸事件处理等。通过学习和理解这些代码,开发者可以更好地掌握SurfaceView在...

    Android使用SurfaceView实现墨迹天气的风车效果-IT计算机-毕业设计.zip

    本示例“Android使用SurfaceView实现墨迹天气的风车效果”是一个很好的学习资源,适用于毕业设计或论文研究。这个项目主要展示了如何利用Android的SurfaceView组件来创建类似墨迹天气应用中的风车动画效果。下面将...

    SurfaceView使用示例

    SurfaceView是Android系统中一种特殊的View,主要用于处理高性能、低延迟的图形绘制,例如游戏画面或者视频播放等场景。在Android应用开发中,SurfaceView通过将渲染操作与UI线程分离,提高了绘制效率,避免了因为UI...

    安卓Android源码——安卓Android使用SurfaceView实现墨迹天气的风车效果.zip

    在安卓应用开发中,SurfaceView ...总之,通过理解SurfaceView的工作机制,我们可以利用其特性实现高性能的图形绘制,如这个例子中的风车效果。通过不断学习和实践,开发者可以创造出更多富有创意和互动性的安卓应用。

    Android_surfaceView与layout屏幕适配总结

    至于`SurfaceView_Test.rar`和`Layout_Test.rar`这两个压缩包,它们可能包含了演示如何在实际项目中应用上述适配策略的示例代码。解压并分析这些代码可以帮助开发者更直观地理解`SurfaceView`和`layout`在屏幕适配中...

    android之view和surfaceview用法示例汇总

    在Android开发中,View和SurfaceView是两种非常重要的视图组件,它们用于在屏幕上显示内容和处理用户交互。本文将详细解析View和SurfaceView的基本概念、用法以及它们之间的区别,通过实例代码来帮助理解。 **一、...

    android surfaceview自定义拍照 绘制头像轮廓

    这个项目"android surfaceview自定义拍照 绘制头像轮廓"是基于网上现有的示例代码进行了修改,用于实现一个自定义的拍照功能,并且在拍摄的照片上能够绘制出人像的轮廓。下面我们将深入探讨`SurfaceView`以及如何...

    android View、SurfaceView Demo

    AnimateViewActivity这个名字暗示这是一个演示如何在View或者SurfaceView中实现动画的示例。在Android中,可以使用各种方法实现动画,如属性动画(Property Animation)、帧动画(Frame Animation)和补间动画...

    android SurfaceView游戏框架

    SurfaceView是Android系统中的一个View类,它的特点在于它拥有自己的Surface,这个Surface位于应用程序窗口的底层,并且有自己的绘制线程。这意味着SurfaceView可以在不阻塞主线程的情况下进行频繁的绘图操作,这...

    Android自定义SurfaceView——实现画板功能

    本示例中的“Android自定义SurfaceView——实现画板功能”旨在教你如何利用`SurfaceView`创建一个可以画画的应用。`SurfaceView`是Android系统提供的一种用于高效显示动态图像的视图组件,它拥有自己的渲染线程,...

    安卓Android源码——SurfaceView添加组件view不被组件覆盖.zip

    `Android SurfaceView添加组件view不被组件覆盖` 这个文件可能是示例代码或者详细教程,里面应该包含了如何将这些概念应用到实际项目中的具体步骤。 总的来说,处理 `SurfaceView` 与其他组件的层次关系是安卓开发...

Global site tag (gtag.js) - Google Analytics