目录
1.view的刷新
2.View和SurfaceView主要区别
3.SurfaceView使用模板
4.示例-绘制正弦函数
5.根据触屏XY坐标绘制路径
在自定义view时候,如果要重绘View,我们会调用invalidate(),如果同时某些子控件的位置等也需要变化,我们还会调用requestLayout()。在通知控件的重绘方式上,可以选择handler或者控件自身自带的post(new Runnable)方法。
局限:系统通过发出VSYNC信号通知屏幕重绘的频率为16ms,如果重绘时候执行逻辑操作太多,就会卡顿,甚至阻断主线程。
其实有时候,可以用surfaceView替代view,去做一些频繁的刷新工作。
1.view主要适用与主动刷新,SurfaceView适用于被动刷新
2.view在主线程对画面进行刷新,SurfaceView会自起子线程对画面刷新
3.view在绘图时没有双缓冲机制,SurfaceView在底层实现机制中实现了双缓冲机制
所有,当我们需要频繁刷新,或者刷新是需要处理大量数据逻辑,便可选择SurfaceView。
大部分SurfaceView绘图都可使用的模板
public class MSur extends SurfaceView implements SurfaceHolder.Callback, Runnable {
private SurfaceHolder surfaceHolder;
//绘图对象
private Canvas canvas;
//控制线程是否去绘制
private boolean isDrawing;
public MSur(Context context) {
super(context);
initView();
}
public MSur(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public MSur(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
public void initView() {
surfaceHolder = getHolder();
surfaceHolder.addCallback(this);
setFocusable(true);
setFocusableInTouchMode(true);
this.setKeepScreenOn(true);
//surfaceHolder.setFormat(PixelFormat.OPAQUE);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
isDrawing = true;
new Thread(this).start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
isDrawing = false;
}
@Override
public void run() {
while (isDrawing) {
draw();
}
}
private void draw() {
try {
//拿到绘图对象
canvas = surfaceHolder.lockCanvas();
//绘制内容
} catch (Exception e) {
Log.e("draw: ", e.toString());
} finally {
//将绘图的内容提交
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
3和比较重要的地方:
1.通过boolean值标志位,去控制界面是否重绘
2.通过SurfaceHolder拿到绘图对象
3.绘制成功后,提交绘制内容
核心思想:通过子线程去计算绘制的正弦函数的路径,在draw方法中用lockCanvas()获取到的绘图对象去绘制路径。
代码:修改模板中的run方法和绘制的内容。
public class MSur extends SurfaceView implements SurfaceHolder.Callback, Runnable {
private SurfaceHolder surfaceHolder;
private Canvas canvas;
private boolean isDrawing;
//绘制路径
private Path mPath;
//path中每个点的坐标
private int x,y=0;
private Paint paint;
public MSur(Context context) {
super(context);
initView();
}
public MSur(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public MSur(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
public void initView() {
surfaceHolder = getHolder();
surfaceHolder.addCallback(this);
setFocusable(true);
setFocusableInTouchMode(true);
this.setKeepScreenOn(true);
//surfaceHolder.setFormat(PixelFormat.OPAQUE);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
isDrawing = true;
mPath = new Path();
mPath.moveTo(0,200);
paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5);
paint.setColor(Color.GREEN);
paint.setAntiAlias(true);
new Thread(this).start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
isDrawing = false;
}
@Override
public void run() {
while (isDrawing) {
draw();
x += 1;
y = (int) (200 * Math.sin(x * 2 * Math.PI / 180)+200);
mPath.lineTo(x,y);
}
}
private void draw() {
try {
//拿到绘图对象
canvas = surfaceHolder.lockCanvas();
canvas.drawColor(Color.WHITE);
canvas.drawPath(mPath,paint);
//绘制内容
} catch (Exception e) {
Log.e("draw: ", e.toString());
} finally {
//将绘图的内容提交
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
效果:
效果:
代码:
public class MSur extends SurfaceView implements SurfaceHolder.Callback, Runnable {
private SurfaceHolder surfaceHolder;
private Canvas canvas;
private boolean isDrawing;
//绘制路径
private Path mPath;
private Paint paint;
public MSur(Context context) {
super(context);
initView();
}
public MSur(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public MSur(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
public void initView() {
surfaceHolder = getHolder();
surfaceHolder.addCallback(this);
setFocusable(true);
setFocusableInTouchMode(true);
this.setKeepScreenOn(true);
//surfaceHolder.setFormat(PixelFormat.OPAQUE);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
isDrawing = true;
mPath = new Path();
paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(20);
paint.setColor(Color.GREEN);
paint.setPathEffect(new CornerPathEffect(10));
paint.setAntiAlias(true);
new Thread(this).start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
isDrawing = false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
Log.e("onTouchEvent: ", "路径x=" + x);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mPath.moveTo(x, y);
break;
case MotionEvent.ACTION_MOVE:
mPath.lineTo(x, y);
break;
}
return true;
}
@Override
public void run() {
long start = System.currentTimeMillis();
while (isDrawing) {
draw();
}
long end = System.currentTimeMillis();
//加上线程睡眠时间,防止太频繁的绘制
if(end-start<=100){
try {
Thread.sleep(100-(end-start));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void draw() {
try {
//拿到绘图对象
canvas = surfaceHolder.lockCanvas();
canvas.drawColor(Color.WHITE);
canvas.drawPath(mPath, paint);
//绘制内容
} catch (Exception e) {
Log.e("draw: ", e.toString());
} finally {
//将绘图的内容提交
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}