一、SurfaceView的介绍
在前面我们已经会自定义View,使用canvas绘图,但是View的绘图机制存在一些缺陷。
1、View缺乏双缓冲机制。
2、程序必须重绘整个View上显示的图片,比较耗资源。
3、非UI线程无法更新View组件,所以会占用主线程资源,当需要在主线程中处理逻辑的时候会很慢。
在Android中为我们提供了一个SurfaceView来替代View实现绘制图形,一般在游戏绘图方面应用较广,所以如果是比较复杂的绘图建议使用SurfaceView.
二、SurfaceView的绘图机制
SurfaceView一般会与SurfaceHolder结合使用,SurfaceHolder用于与之关联的SurfaceView上绘图,调用SurfaceView的getHolder()方法可获取SurfaceView关联的SurfaceHolder.
SurfaceHolder提供了lockCanvas和lockCanvas(Rect dirty)来锁定绘图区域,并获取到该区域的画布(Canvas)我们通过该画布就可以进行图形的绘制了。
三、SurfaceView使用实例
1、一个简单的使用(绘制在UI线程)
package com.test.surfaceview; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.os.Bundle; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.View.OnTouchListener; import com.example.testsurfaceview.R; public class MainActivity extends Activity{ private SurfaceHolder holder; private Paint paint; private Rect rect; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); paint = new Paint(); rect = new Rect(); SurfaceView surface = (SurfaceView)findViewById(R.id.show); holder = surface.getHolder(); //由系统毁掉的三个函数 holder.addCallback(new SurfaceHolder.Callback() { @Override public void surfaceDestroyed(SurfaceHolder holder) { } @Override public void surfaceCreated(SurfaceHolder holder) { Canvas canvas = holder.lockCanvas(); Bitmap bitmap = BitmapFactory.decodeResource( MainActivity.this.getResources(), R.drawable.ic_launcher); canvas.drawBitmap(bitmap, 0, 0, null); holder.unlockCanvasAndPost(canvas); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } }); //绑定事件监听 surface.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if(event.getAction() == MotionEvent.ACTION_DOWN){ int cx = (int)event.getX(); int cy = (int)event.getY(); rect.set(cx - 50, cy - 50, cx + 50, cy + 50); //锁定一个固定区域并锁定 Canvas canvas = holder.lockCanvas(rect); //保存画布当前状态 canvas.save(); //旋转画布 canvas.rotate(30, cx, cy); paint.setColor(Color.RED); //绘制方块 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; } }); } }2、在非UI线程中绘制
package com.test.surfaceview; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.os.AsyncTask; import android.util.AttributeSet; import android.view.SurfaceHolder; import android.view.SurfaceView; import com.example.testsurfaceview.R; /** * 阳光小强 http://blog.csdn.net/dawanganban * * @author Administrator * */ public class MySurfaceView extends SurfaceView { private Context context; private Rect rect; private Paint paint; private AppStartDrawView appStartDrawView; public MySurfaceView(Context context, AttributeSet attrs) { super(context, attrs); this.context = context; rect = new Rect(); paint = new Paint(); appStartDrawView = new AppStartDrawView(); this.getHolder().addCallback(appStartDrawView); } /** * 停止动画 */ public void stopAnim() { appStartDrawView.cancel(true); } private class AppStartDrawView extends AsyncTask<Void, Integer, Void> implements SurfaceHolder.Callback { private boolean isStarted = false; private SurfaceHolder holder; @Override public void surfaceCreated(SurfaceHolder holder) { this.holder = holder; //绘制一个图片 Canvas canvas = holder.lockCanvas(); Bitmap bitmap = BitmapFactory.decodeResource( context.getResources(), R.drawable.ic_launcher); canvas.drawBitmap(bitmap, 0, 0, null); holder.unlockCanvasAndPost(canvas); if (!isStarted) { this.execute(); isStarted = true; } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { this.holder = holder; } @Override public void surfaceDestroyed(SurfaceHolder holder) { isStarted = false; holder = null; } @Override protected Void doInBackground(Void... params) { int cx = 0; int cy = 0; while(!isCancelled()){ //绘制动画 //TODO ..... rect.set(cx - 50, cy - 50, cx + 50, cy + 50); //锁定一个固定区域并锁定 Canvas canvas = holder.lockCanvas(rect); //保存画布当前状态 canvas.save(); //旋转画布 canvas.rotate(30, cx, cy); paint.setColor(Color.RED); //绘制方块 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); //TODO .... try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } cx += 60; cy += 60; if(cx >= 400){ stopAnim(); } } return null; } } }