我的绘图应用程序有问题。我需要抓住正确的触摸屏并将它们绘制到画布上。改变画笔的大小是正常的。但是当我更改透明度设置时,程序无法正常工作。它在前一个路径上施加了新的路径,并且透明度丢失了。 Screenshot。哪里可能出错?我需要你的帮助。谢谢。
这是我的SurfaceView代码:
public class PainterView extends SurfaceView implements SurfaceHolder.Callback {
private PainterThread painterThread;
private BrushParameters brushParameters;
private Bitmap bitmap;
public PainterView(Context context, AttributeSet attrs) {
super(context, attrs);
SurfaceHolder holder = getHolder();
holder.addCallback(this);
brushParameters = new BrushParameters();
}
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
setWillNotDraw(false);
getThread().setRunning(true);
getThread().start();
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int width, int height) {
if (bitmap == null) {
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
getThread().setBitmap(bitmap, true);
} else {
getThread().setBitmap(bitmap, false);
}
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
getThread().setRunning(false);
boolean retry = true;
while (retry) {
try {
getThread().join();
retry = false;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
painterThread = null;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
painterThread.startDraw(x, y);
break;
case MotionEvent.ACTION_MOVE:
painterThread.continueDraw(x, y);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
painterThread.finishDraw(x, y);
break;
}
return true;
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(bitmap, 0, 0, null);
}
public BrushParameters getBrushParameters() {
return brushParameters;
}
public void setBrushColor(int color) {
brushParameters.setColor(color);
getThread().setBrushParameters(brushParameters);
}
public void setBrushSize(int size) {
brushParameters.setSize(size);
getThread().setBrushParameters(brushParameters);
}
public void setBrushAlpha(int alpha) {
brushParameters.setAlpha(alpha);
getThread().setBrushParameters(brushParameters);
}
public PainterThread getThread() {
if (painterThread == null) {
painterThread = new PainterThread(getHolder(), this);
}
return painterThread;
}
}
我的Thread课程:
public class PainterThread extends Thread {
private SurfaceHolder surfaceHolder;
private PainterView painterView;
private boolean running = false;
private Paint paint;
private Path path;
private Bitmap mBitmap;
private Canvas mCanvas;
private float lastX, lastY;
private static float TOUCH_TOLERANCE = 4;
public PainterThread(SurfaceHolder surfaceHolder, PainterView painterView) {
this.surfaceHolder = surfaceHolder;
this.painterView = painterView;
path = new Path();
paint = new Paint();
paint.setAntiAlias(true);
paint.setDither(true);
paint.setColor(Color.BLACK);
paint.setAlpha(255);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
}
public void setRunning(boolean running) {
this.running = running;
}
@Override
public void run() {
Canvas mCanvas;
while (running) {
mCanvas = null;
try {
mCanvas = surfaceHolder.lockCanvas(null);
synchronized (surfaceHolder) {
if (mCanvas != null) {
mCanvas.drawBitmap(mBitmap, 0, 0, paint);
painterView.postInvalidate();
}
}
} finally {
if (mCanvas != null) {
surfaceHolder.unlockCanvasAndPost(mCanvas);
}
}
}
}
public void setBitmap(Bitmap bitmap, boolean clear) {
mBitmap = bitmap;
if (clear) {
mBitmap.eraseColor(Color.WHITE);
}
mCanvas = new Canvas(mBitmap);
}
public void setBrushParameters(BrushParameters brushParameters) {
paint.setColor(brushParameters.getColor());
paint.setAlpha(brushParameters.getAlpha());
paint.setStrokeWidth(brushParameters.getSize());
}
public void startDraw(float x, float y) {
path.reset();
path.moveTo(x, y);
lastX = x;
lastY = y;
}
public void continueDraw(float x, float y) {
float dx = Math.abs(x - lastX);
float dy = Math.abs(y - lastY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
path.quadTo(lastX, lastY, (x + lastX) / 2, (y + lastY) / 2);
mCanvas.drawPath(path, paint);
lastX = x;
lastY = y;
}
}
public void finishDraw(float x, float y) {
path.moveTo(x, y);
mCanvas.drawPath(path, paint);
}
}
感谢您的帮助。找不到问题的原因,我失去了fiew的日子......
答案 0 :(得分:0)
我建议摆脱SurfaceView。你有一些看起来很混乱的代码(例如setBitmap()
设置mCanvas
,但这会被run()
)循环覆盖,我认为你只是让自己的生活更加艰难
SurfaceViews有两个部分,Surface和View。 Surface是一个单独的图层(默认情况下)位于View图层后面。 SurfaceView的View部分通常只是一个透明孔,可让您“透视”后面的Surface层。
在您的情况下,您已在View对象中覆盖onDraw()
,因此您实际上是在View中绘图。在你的另一个线程中,你将相同的Bitmap绘制到Surface上。即使您的位图具有透明像素,您也会看到两个相同的位图层叠在一起。
看起来你在两个同时执行的线程之间共享一个Bitmap和一个Canvas,这是一个不快乐的秘诀。
如果你摆脱SurfaceView,只使用custom View,我认为一切都会更有意义。另一种方法是摆脱onDraw()
和调用postInvalidate()
并在Surface上执行所有操作,但是为了利用硬件加速渲染,最好使用自定义视图。