10.3 SurfaceView
public class SurfaceGesturePath extends SurfaceView {
private Path mPath;
private Paint mPaint;
public SurfaceGesturePath(Context context) {
this(context, null);
}
public SurfaceGesturePath(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SurfaceGesturePath(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mPaint = new Paint();
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(5);
mPaint.setColor(Color.RED);
mPath = new Path();
//默认为黑色背景 修改为透明
this.setZOrderOnTop(true);
this.getHolder().setFormat(PixelFormat.TRANSLUCENT);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
if (event.getAction() == MotionEvent.ACTION_DOWN) {
mPath.moveTo(x, y);
return true;
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
mPath.lineTo(x, y);
}
drwacanvas();
return super.onTouchEvent(event);
}
//由于机制不同 建议这么来绘制
private void drwacanvas() {
new Thread(){
@Override
public void run() {
SurfaceHolder holder = getHolder();
Canvas canvas = holder.lockCanvas();
canvas.drawPath(mPath, mPaint);
holder.unlockCanvasAndPost(canvas);
}
}.start();
}
}
可以通过以上代码大致 了解 了SurfaceView 虽然派生自View ,但是他自带画布,具有双缓冲技术,所以绘制的时候使用缓冲画布.
注意我使用drawColor 和 xml 设置背景色 都无效,默认是黑色背景,可以设置成白色透明,其他颜色如何设置暂时不知晓
为什么要加锁
特性:SurfaceView 中的缓冲画布 在线程中是可以更新的.
如果同时存在诸多线程去更新,那么绘制的就会很乱,所以需要加锁.
...................而加锁就会造成一个问题,当画布被占用或者缓存canvas没有被创建的时候,surfaceHolder.lockCanvas函数会返回null,这样一来,如果存在多个线程同时操作缓冲画布的情况,则不仅需要对画布做判空处理,也需要在画布为空的时候添加重试策略,
仿墨迹天气背景
/**
* -----------------------------
* Created by zqf on 2020/8/3.
* 仿墨迹天气背景
* ---------------------------
*/
public class MojiTianqiView extends SurfaceView {
private SurfaceHolder surfaceHolder;
/**
* 线程标识
*/
private boolean flag = false;
private Bitmap bitmap_bg;
private Canvas mCanvas;
/**
* 开始绘制的图片的X坐标
*/
private int mBitposX;
private int mSurfaceWidth;
//背景 移动状态
private enum State {
LEFT, RIGHT
}
//默认为向左
private State state = State.LEFT;
//背景画布移动步伐
private final int BITMAP_STEP = 1;
public MojiTianqiView(Context context) {
this(context, null);
}
public MojiTianqiView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MojiTianqiView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
surfaceHolder = getHolder();
surfaceHolder.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
flag = true;
startAnimation();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
flag = false;
}
});
}
private void startAnimation() {
mSurfaceWidth = getWidth();
int mSurfaceHeight = getHeight();
int mWidth = mSurfaceWidth * 3 / 2;
/**
* 将图片宽度缩放带屏幕的3/2倍,高度充满屏幕
*/
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.bg);
bitmap_bg = Bitmap.createScaledBitmap(bitmap, mWidth, mSurfaceHeight, true);
//开始绘图
Thread thread = new Thread() {
@Override
public void run() {
while (flag) {
mCanvas = surfaceHolder.lockCanvas();
DrawView();
surfaceHolder.unlockCanvasAndPost(mCanvas);
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
thread.start();
}
/**
* 进行绘制
*/
private void DrawView() {
//绘制背景
mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
mCanvas.drawBitmap(bitmap_bg, mBitposX, 0, null);
/** 图片滚动效果 **/
switch (state) {
case LEFT:
mBitposX -= BITMAP_STEP;
break;
case RIGHT:
mBitposX += BITMAP_STEP;
break;
default:
break;
}
if (mBitposX <= -mSurfaceWidth / 2) {
state = State.RIGHT;
}
if (mBitposX >= 0) {
state = State.LEFT;
}
}
}
数字闪烁类似
public class NumberView extends SurfaceView {
private Paint mPaint;
private int height;
public NumberView(Context context) {
this(context, null);
}
public NumberView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public NumberView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mPaint = new Paint();
mPaint.setColor(Color.RED);
mPaint.setTextSize(ConvertUtils.sp2px(30));
//默认为黑色背景 修改为透明
this.setZOrderOnTop(true);
this.getHolder().setFormat(PixelFormat.TRANSLUCENT);
height = ConvertUtils.dp2px(100);
getHolder().addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
drawText(holder);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
});
}
/**
* 开始绘制
*/
private void drawText(SurfaceHolder holder) {
Thread thread = new Thread() {
@Override
public void run() {
while (true) {
for (int i = 0; i < 10; i++) {
Canvas mCanvas = holder.lockCanvas();
//俩种效果
// mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
if (mCanvas != null) {
mCanvas.drawText(i + "", i * 30, height / 2, mPaint);
}
holder.unlockCanvasAndPost(mCanvas);
try {
Thread.sleep(800);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
};
thread.start();
}
}
一次性绘制所有数字
Thread thread = new Thread() {
@Override
public void run() {
Canvas mCanvas = holder.lockCanvas();
for (int i = 0; i < 10; i++) {
if (mCanvas != null) {
mCanvas.drawText(i + "", i * 60, height / 2, mPaint);
}
}
holder.unlockCanvasAndPost(mCanvas);
}
};
thread.start();
public class NumberView extends SurfaceView {
private Paint mPaint;
private int height;
private boolean flag = true;
public NumberView(Context context) {
this(context, null);
}
public NumberView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public NumberView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mPaint = new Paint();
mPaint.setColor(Color.RED);
mPaint.setTextSize(ConvertUtils.sp2px(30));
//默认为黑色背景 修改为透明
this.setZOrderOnTop(true);
this.getHolder().setFormat(PixelFormat.TRANSLUCENT);
height = ConvertUtils.dp2px(100);
getHolder().addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
drawText(holder);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
});
}
private List mInts = new ArrayList<>();
/**
* 开始绘制
*/
private void drawText(SurfaceHolder holder) {
Thread thread = new Thread() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
Canvas mCanvas = holder.lockCanvas();
mInts.add(i);
if (mCanvas != null) {
for (int j = 0; j < mInts.size(); j++) {
mCanvas.drawText(mInts.get(j) + "", j * 60, height / 2, mPaint);
}
try {
Thread.sleep(800);
} catch (InterruptedException e) {
e.printStackTrace();
}
holder.unlockCanvasAndPost(mCanvas);
}
}
}
};
thread.start();
}
}
带背景
public class NumberView extends SurfaceView {
private Paint mPaint;
private int height;
private boolean flag = true;
public NumberView(Context context) {
this(context, null);
}
public NumberView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public NumberView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mPaint = new Paint();
mPaint.setColor(Color.RED);
mPaint.setTextSize(ConvertUtils.sp2px(30));
//默认为黑色背景 修改为透明
this.setZOrderOnTop(true);
this.getHolder().setFormat(PixelFormat.TRANSLUCENT);
height = ConvertUtils.dp2px(100);
getHolder().addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
drawText(holder);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
});
}
private List mInts = new ArrayList<>();
/**
* 开始绘制
*/
private void drawText(SurfaceHolder holder) {
Thread thread = new Thread() {
@Override
public void run() {
//先进行清屏操作
while (true) {
Rect dirtyRect = new Rect(0, 0, 1, 1);
Canvas canvas = holder.lockCanvas(dirtyRect);
Rect canvasRect = canvas.getClipBounds();
if (getWidth() == canvasRect.width() && getHeight() == canvasRect.height()) {
canvas.drawColor(Color.WHITE);
holder.unlockCanvasAndPost(canvas);
} else {
holder.unlockCanvasAndPost(canvas);
break;
}
}
//画图
for (int i = 0; i < 10; i++) {
//间隔
int itemWidth = 80;
//行高
int itemHeight = height;
Rect rect = new Rect(i * itemWidth, 0, (i + 1) * itemWidth - 10, itemHeight);
Canvas canvas = holder.lockCanvas(rect);
if (canvas != null) {
canvas.drawColor(Color.GREEN);
canvas.drawText(i+"",i*itemWidth+10, itemHeight/2, mPaint);
}
holder.unlockCanvasAndPost(canvas);
try {
Thread.sleep(800);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
thread.start();
}
}