SurfaceView小结
2019-03-19 本文已影响0人
Dane_404
1、使用SurfaceView的原因
View刷新重新绘制的时间间隔是16ms,如果可以在16ms以内绘制完, 则没有什么问题,如果绘制逻辑复杂,更新又很频繁,这样界面就会卡顿,就必须使用SurfaceView了。
区别:
- View在主线程中对页面进行刷新,而SurfaceView则开启一个子线程来对页面进行刷新。
- View在绘图时没有实现双缓冲机制,SurfaceView在底层机制中就实现了双缓冲机制。
- 双缓冲技术:
双缓冲技术是游戏开发中的一个重要的技术。当一个动画争先显示时,程序又在改变它,前面还没有显示完,程序又请求重新绘制,这样屏幕就会不停地闪烁。而双缓冲技术是把要处理的图片在内存中处理好之后,再将其显示在屏幕上。双缓冲主要是为了解决 反复局部刷屏带来的闪烁。把要画的东西先画到一个内存区域里,然后整体的一次性画出来。
2、使用SurfaceView
做个小Demo,一个涂鸦Demo
涂鸦:
public class DoodleSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Paint mPaint;
private Canvas mCanvas;
private Path mPath;
public DoodleSurfaceView (Context context) {
this(context, null);
}
public DoodleSurfaceView (Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public DoodleSurfaceView (Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
initPaintAndPath();
}
private void initPaintAndPath() {
mPaint = new Paint();
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(5);
mPaint.setAntiAlias(true);
mPaint.setColor(Color.BLACK);
mPath = new Path();
}
private void init() {
mHolder = getHolder();
mHolder.addCallback(this);
setFocusable(true);
setKeepScreenOn(true); //保持屏幕常亮
setFocusableInTouchMode(true);
}
//创建时调用
@Override
public void surfaceCreated(SurfaceHolder holder) {
mCanvas = mHolder.lockCanvas();
mCanvas.drawColor(Color.WHITE);
mHolder.unlockCanvasAndPost(mCanvas);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
private void draw() {
mCanvas = mHolder.lockCanvas();
mCanvas.drawColor(Color.WHITE);
mCanvas.drawPath(mPath, mPaint);
mHolder.unlockCanvasAndPost(mCanvas);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mPath.moveTo(x, y);
break;
case MotionEvent.ACTION_MOVE:
mPath.lineTo(x, y);
draw();
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
}