SurfaceView
- Surface——表面,这个概念在图形编程中常常被提到。基本上我们可以把它当作显存的一个映射,写入到Surface 的内容 可以被直接复制到显存从而显示出来,这使得显示速度非常快。
- 可以直接从内存或者DMA【直接存储器访问(Direct Memory Access)】等硬件接口取得图像数据,是个非常重要的绘图容器。
- 它的特性是:可以在主线程之外的线程中向屏幕绘图。这样可以避免画图任务繁重的时候造成主线程阻塞,从而提高了程序的反应速度。当界面的动画元素较多,而且很多都需要通过定时器来控制这些动画元素的移动,就考虑使用SurfaceView。游戏开发中多用到SurfaceView,游戏中的背景、人物、动画等等尽量在画布canvas中画出。
- View缺乏双缓冲机制;
- 当程序需要更新View上的图像时,程序必须重绘View上显示的整张图片;
- 新线程无法直接更新View组件。
A. 具有独立的绘图表面;B. 需要在宿主窗口上挖一个洞来显示自己;C. 它的UI绘制可以在独立的线程中进行,这样就可以进行复杂的UI绘制,并且不会影响应用程序的主线程响应用户输入。
- SurfaceView.getHolder()获得SurfaceHolder对象 ---->
- SurfaceHolder.addCallback(callback)添加回调方法---->
- 实现SurfaceHolder.Callback接口 ,重写其中的方法---->
- SurfaceHolder.lockCanvas()获得Canvas对象并锁定画布---->
- Canvas绘画 ---->
- SurfaceHolder.unlockCanvasAndPost(Canvas canvas)结束锁定画图,并提交改变,将图形显示。
(1)、abstract void addCallback(SurfaceHolder.Callback callback);
给SurfaceView当前的持有者一个回调对象。
(2)、abstract Canvas lockCanvas();
锁定画布,一般在锁定后就可以通过其返回的画布对象Canvas,在其上面画图等操作了。
(3)、abstract Canvas lockCanvas(Rect dirty);
锁定画布的某个区域进行画图等..因为画完图后,会调用下面的unlockCanvasAndPost来改变显示内容。
相对部分内存要求比较高的游戏来说,可以不用重画dirty外的其它区域的像素, 只对Rect所圈出来的区域进行更新,通过这种方式可以 提高画面的更新速度。
(4)、abstract void unlockCanvasAndPost(Canvas canvas);
结束锁定画图,并提交改变。
B、将定义好的路径绘制在画布上:1、addArc() 添加弧形路径2、addCircle() 添加圆形路径3、addOval() 添加椭圆形路径4、addRect() 添加矩形路径5、addRoundRect() 添加圆角矩形路径6、moveTo() 设置绘制直线的起始点7、lineTo() 绘制直线8、quadTo() 绘制线段轨迹9、close() 闭合路径
三、实例代码:1、drawPath() : 绘制路径2、drawTextOnPath() : 沿着指定路径绘制字符串
publicclass MainActivity extends Activity {
private SurfaceView surfaceView_main;
private SurfaceHolder surfaceHolder;
private MediaPlayer mediaPlayer = null;
private String filePath = "";
privateintposition = 0;
@Override
protectedvoid onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
filePath = "/mnt/sdcard/Download/2050.3gp";
mediaPlayer = new MediaPlayer();
surfaceView_main = (SurfaceView) findViewById(R.id.surfaceView_main);
surfaceHolder = surfaceView_main.getHolder();
surfaceHolder.addCallback(new SurfaceHolder.Callback() {
@Override
publicvoid surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
@Override
publicvoid surfaceCreated(SurfaceHolder holder) {
if (position > 0) {
play();
mediaPlayer.seekTo(position);
position = 0;
}
}
@Override
publicvoid surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
// TODO Auto-generated method stub
}
});
}
publicvoid clickButton(View view) {
switch (view.getId()) {
case R.id.imageView_main_play:
if (!mediaPlayer.isPlaying()) {
play();
}
break;
case R.id.imageView_main_pause:
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
} else {
mediaPlayer.start();
}
break;
case R.id.imageView_main_stop:
mediaPlayer.stop();
break;
}
}
privatevoid play() {
try {
mediaPlayer.reset();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(filePath);
mediaPlayer.setDisplay(surfaceHolder);
mediaPlayer.prepare();
mediaPlayer.start();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
protectedvoid onPause() {
super.onPause();
if (mediaPlayer.isPlaying()) {
position = mediaPlayer.getCurrentPosition();
mediaPlayer.pause();
}
}
@Override
protectedvoid onDestroy() {
super.onDestroy();
if (mediaPlayer != null) {
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
mediaPlayer.release();
}
}
@Override
publicboolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
returntrue;
}
}
publicclass MainActivity extends Activity {
private SurfaceView surfaceView_main;
private SurfaceHolder surfaceHolder;
@Override
protectedvoid onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
surfaceView_main = (SurfaceView) findViewById(R.id.surfaceView_main);
surfaceHolder = surfaceView_main.getHolder();
surfaceHolder.addCallback(new SurfaceHolder.Callback() {
@Override
publicvoid surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
@Override
publicvoid surfaceCreated(SurfaceHolder holder) {
new MyThread().start();
}
@Override
publicvoid surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
// TODO Auto-generated method stub
}
});
}
class MyThread extends Thread {
@Override
publicvoid run() {
super.run();
Bitmap bitmapBg = null;
Bitmap bitmapBear = null;
int count = 1;
int bgX = 0;
intbearX = 0;
AssetManager assetManager = getResources().getAssets();
try {
bitmapBg = BitmapFactory.decodeStream(assetManager
.open("bg.png"));
while (true) {
bitmapBear = BitmapFactory.decodeStream(assetManager
.open("bear" + count + ".png"));
Canvas canvas = surfaceHolder.lockCanvas();
canvas.drawColor(Color.GRAY);
Paint paint = new Paint();
canvas.drawBitmap(bitmapBg, bgX, 0, paint);
canvas.drawBitmap(bitmapBg, bgX - 1024, 0, paint);
canvas.drawBitmap(bitmapBear, 200, 100, paint);
surfaceHolder.unlockCanvasAndPost(canvas);
bgX += 2;
if (bgX > 1024) {
bgX = 0;
}
Thread.sleep(30);
count++;
if (count > 8) {
count = 1;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
publicboolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
returntrue;
}
}
publicclass MainActivity extends Activity {
private Camera mCamera = null;
private SurfaceView surfaceView_main;
private SurfaceHolder surfaceHolder;
@Override
protectedvoid onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
privatevoid initSurfaceView() {
surfaceView_main = (SurfaceView) findViewById(R.id.surfaceView_main);
surfaceHolder = surfaceView_main.getHolder();
// surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
surfaceHolder.addCallback(new SurfaceHolder.Callback() {
@Override
publicvoid surfaceDestroyed(SurfaceHolder holder) {
if (mCamera != null) {
mCamera.stopPreview();
}
}
@Override
publicvoid surfaceCreated(SurfaceHolder holder) {
try {
mCamera.setPreviewDisplay(surfaceHolder);
mCamera.startPreview();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
publicvoid surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
// TODO Auto-generated method stub
}
});
}
@Override
protectedvoid onResume() {
super.onResume();
if (mCamera == null) {
mCamera = Camera.open();
}
}
@Override
protectedvoid onPause() {
super.onPause();
if (mCamera != null) {
mCamera.release();
}
}
publicvoid clickButton(View view) {
switch (view.getId()) {
case R.id.button_main_preview:
initSurfaceView();
break;
case R.id.button_main_takepicture:
mCamera.takePicture(shutterCallback, rawCallback, jpegCallback);
break;
}
}
ShutterCallback shutterCallback = new ShutterCallback() {
@Override
publicvoid onShutter() {
// TODO Auto-generated method stub
}
};
PictureCallback rawCallback = new PictureCallback() {
@Override
publicvoid onPictureTaken(byte[] data, Camera camera) {
// TODO Auto-generated method stub
}
};
PictureCallback jpegCallback = new PictureCallback() {
@Override
publicvoid onPictureTaken(byte[] data, Camera camera) {
setTitle(data.length + "");
}
};
@Override
publicboolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
returntrue;
}
}
良心的公众号,更多精品文章,不要忘记关注哈
《Android和Java技术栈》