SurfaceView
程序员文章站
2022-03-29 19:30:14
...
1.为什么用SurfaceView:SurfaceView比View更适用于频繁刷新,surfaceview通常会通过一个子线程来进行页面刷新,View会直接在主线程中对画面进行刷新。所以当我们的自定义View需要频繁刷新,或者刷新时数据处理量比较大就可以考虑使用surfaceview来代替View。
2.模版:
public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback,Runnable{
private SurfaceHolder mHolder;
private Canvas mCanvas;
private boolean mIsDrawing;
public MySurfaceView(Context context) {
this(context,null);
}
public MySurfaceView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public MySurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
mHolder = getHolder();
mHolder.addCallback(this);
setFocusable(true);
setFocusableInTouchMode(true);
this.setKeepScreenOn(true);
}
@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();
}catch (Exception e){
}finally {
if(mCanvas!=null){
mHolder.unlockCanvasAndPost(mCanvas);
}
}
}
}
3.正弦曲线:
public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback,Runnable{
private SurfaceHolder mHolder;
private Canvas mCanvas;
private boolean mIsDrawing;
public MySurfaceView(Context context) {
this(context,null);
}
public MySurfaceView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public MySurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
int x;
int y;
Path mPath;
Paint mPaint;
private void init() {
mHolder = getHolder();
mHolder.addCallback(this);
setFocusable(true);
setFocusableInTouchMode(true);
this.setKeepScreenOn(true);
mPath = new Path();
mPaint = new Paint();
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(10);
}
@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();
x+=1;
y = (int) (100*Math.sin(x*2* Math.PI/180)+400);
mPath.lineTo(x,y);
}
}
// @Override
// public boolean onTouchEvent(MotionEvent event) {
// int x = (int) event.getX();
// int y = (int) event.getY();
// switch (event.getAction()){
// case MotionEvent.ACTION_DOWN:
//
// mPath.moveTo(x,y);
//
// break;
//
// case MotionEvent.ACTION_MOVE:
//
// mPath.lineTo(x,y);
//
// break;
//
// case MotionEvent.ACTION_UP:
//
//
// break;
// }
//
//
// return true;
// }
private void draw(){
try {
mCanvas = mHolder.lockCanvas();
mCanvas.drawColor(Color.WHITE);
mCanvas.drawPath(mPath,mPaint);
}catch (Exception e){
}finally {
if(mCanvas!=null){
mHolder.unlockCanvasAndPost(mCanvas);
}
}
}
}
3.画板
public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback,Runnable{
private SurfaceHolder mHolder;
private Canvas mCanvas;
private boolean mIsDrawing;
public MySurfaceView(Context context) {
this(context,null);
}
public MySurfaceView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public MySurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
int x;
int y;
Path mPath;
Paint mPaint;
private void init() {
mHolder = getHolder();
mHolder.addCallback(this);
setFocusable(true);
setFocusableInTouchMode(true);
this.setKeepScreenOn(true);
mPath = new Path();
mPaint = new Paint();
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(10);
}
@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();
// x+=1;
// y = (int) (100*Math.sin(x*2* Math.PI/180)+400);
// mPath.lineTo(x,y);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
mPath.moveTo(x,y);
break;
case MotionEvent.ACTION_MOVE:
mPath.lineTo(x,y);
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
private void draw(){
try {
mCanvas = mHolder.lockCanvas();
mCanvas.drawColor(Color.WHITE);
mCanvas.drawPath(mPath,mPaint);
}catch (Exception e){
}finally {
if(mCanvas!=null){
mHolder.unlockCanvasAndPost(mCanvas);
}
}
}
}
如果把onTouchEvent的return值改成false或者super就什么都画不出来。super最后结果也是false因为该View并不是clickble所以会返回false,所以问题就是返回false为什么就画不出来了。
之前的困惑:虽然该View并没有消耗这个事件,但是执行了我们重写的ontouchEvent方法,执行了actionDown和actionMove,也就执行mPath.moveTo(x,y);和mPath.lineTo(x,y),理论上来说虽然没有消耗这个事件但是应该有图像。
后来仔细的思考了一下:在actionDown的时候事件没有消耗,之后的move事件就不会走,而我们重写的onTouchEvent方法中的actionDown只有mPath.moveTo(x,y)这个并不会画上去,所以不显示
上一篇: surfaceview
下一篇: SurfaceView
推荐阅读