SurfaceView和View是孪生兄弟,区别:
1.View是主动刷新,而SurfaceView是适用于被动刷新,例如频繁刷新。
2.View是在主线程中刷新,而SurfaceView在子线程来进行页面刷新。
3.View绘图没有实现双缓冲机制,而SurfaceView实现。
使用SurfaceView一般有固定的模板:都要实现SurfaceHolder.Callback,Runnable。下面代码是实现简单的画板。
package com.chen.testsrfaceview;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
private final static String TAG = "cq";
private SurfaceHolder mHolder;
/**
* 用于绘图的canvas
*/
private Canvas mCanvas;
/**
* 子线程标记位
*/
private boolean mIsDrawing;
private Path mPath;
private Paint mPaint;
public MySurfaceView(Context context) {
super(context);
initView();
}
public MySurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public MySurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
private void initView() {
initSurfaceHolder();
initPath();
initPaint();
}
private void initPaint() {
mPaint = new Paint();
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(30);
}
private void initPath() {
mPath = new Path();
}
private void initSurfaceHolder() {
mHolder = getHolder();
mHolder.addCallback(this);
setFocusable(true);
setFocusableInTouchMode(true);
setKeepScreenOn(true);
//不透明的
mHolder.setFormat(PixelFormat.OPAQUE);
}
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
mIsDrawing = true;
new Thread(this).start();
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
mIsDrawing = false;
}
@Override
public void run() {
long start = System.currentTimeMillis();
while (mIsDrawing) {
draw();
}
long end = System.currentTimeMillis();
long difference = end - start;
//当绘制不需要太频繁
if (difference < 100) {
try {
Thread.sleep(100-difference);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void draw() {
try {
mCanvas = mHolder.lockCanvas();
mCanvas.drawColor(Color.WHITE);
mCanvas.drawPath(mPath, mPaint);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != mCanvas) {
mHolder.unlockCanvasAndPost(mCanvas);
}
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
Log.d(TAG, "MotionEvent.ACTION_DOWN");
mPath.moveTo(x, y);
break;
case MotionEvent.ACTION_MOVE:
Log.d(TAG, "MotionEvent.ACTION_MOVE");
mPath.lineTo(x, y);
break;
case MotionEvent.ACTION_UP:
Log.d(TAG, "MotionEvent.ACTION_UP");
break;
}
return true;
}
}