1.SurfaceView与View的区别
- View主要适用于主动更新的情况,而SurfaceView主要适用于被动更新,例如频繁刷新。
- View在主线程中对画面进行刷新,而SurfaceView通常会通过一个子线程对画面进行更新。
- View在绘图时没有使用双缓冲机制,而SurfaceView在底层实现机制中就已经实现了双缓冲机制。
2.SurfaceView的使用
- 创建SurfaceView,需要实现两个接口:SurfaceHolder.Callback和Runnable
- 初始化SurfaceView,初始化SurfaceHolder并注册其回调方法
- 使用SurfaceView,在surfaceCreated()方法中开启子线程进行绘制
SurfaceView的代码模板:
package com.imooc.surfaceviewtest;
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class SurfaceViewTemplate extends SurfaceView
implements SurfaceHolder.Callback, Runnable {
// SurfaceHolder
private SurfaceHolder mHolder;
// 用于绘图的Canvas
private Canvas mCanvas;
// 子线程标志位
private boolean mIsDrawing;
public SurfaceViewTemplate(Context context) {
super(context);
initView();
}
public SurfaceViewTemplate(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public SurfaceViewTemplate(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initView();
}
private void initView() {
mHolder = getHolder();
mHolder.addCallback(this);
setFocusable(true);
setFocusableInTouchMode(true);
this.setKeepScreenOn(true);
//mHolder.setFormat(PixelFormat.OPAQUE);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
mIsDrawing = true;
new Thread(this).start();
}
@Override
public void surfaceChanged(SurfaceHolder holder,
int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mIsDrawing = false;
}
@Override
public void run() {
while (mIsDrawing) {
draw();
}
}
private void draw() {
try {
mCanvas = mHolder.lockCanvas();//获得当前的Canvas绘图对象
// draw sth
} catch (Exception e) {
} finally {
if (mCanvas != null)
//对画布内容进行提交
mHolder.unlockCanvasAndPost(mCanvas);
}
}
}
3.SurfaceView的使用实例
绘制正弦曲线
代码如下:
public class SinView extends SurfaceView
implements SurfaceHolder.Callback, Runnable {
private SurfaceHolder mHolder;
private Canvas mCanvas;
private boolean mIsDrawing;
private int x = 0;
private int y = 0;
private Path mPath;
private Paint mPaint;
public SinView(Context context) {
super(context);
initView();
}
public SinView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public SinView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initView();
}
private void initView() {
mHolder = getHolder();
mHolder.addCallback(this);
setFocusable(true);
setFocusableInTouchMode(true);
this.setKeepScreenOn(true);
mPath = new Path();
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(10);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeJoin(Paint.Join.ROUND);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
mIsDrawing = true;
mPath.moveTo(0, 400);
new Thread(this).start();
}
@Override
public void surfaceChanged(SurfaceHolder holder,
int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mIsDrawing = false;
}
@Override
public void run() {
while (mIsDrawing) {
draw();
x += 1;
y = (int) (100*Math.sin(x * 2 * Math.PI / 180) + 400);
mPath.lineTo(x, y);
}
}
private void draw() {
try {
mCanvas = mHolder.lockCanvas();
// SurfaceView背景
mCanvas.drawColor(Color.WHITE);
mCanvas.drawPath(mPath, mPaint);
} catch (Exception e) {
} finally {
if (mCanvas != null)
mHolder.unlockCanvasAndPost(mCanvas);
}
}
}
参考:Android群英传