问题
I'm trying to do simple painter. The problem that it looks like Android has three independent Canvas and give me it for drawing sequentially.
I made UI with SurfaceView
, took Holder from it.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sv = (SurfaceView) findViewById(R.id.sv);
holder = sv.getHolder();
holder.addCallback(callback);
}
Then took Surface.
@Override
public void surfaceCreated(SurfaceHolder holder) {
surface = holder.getSurface();
}
And by events from OnTouchListener()
draw dots and lines.
private void paintStartDot(float x, float y) {
Canvas canvas = surface.lockCanvas(null);
canvas.drawPoint(x, y, drawPaint);
surface.unlockCanvasAndPost(canvas);
lastX = x;
lastY = y;
}
private void paintEndDot(float x, float y) {
Canvas canvas = surface.lockCanvas(null);
canvas.drawLine(lastX, lastY, x, y, drawPaint);
surface.unlockCanvasAndPost(canvas);
lastX = x;
lastY = y;
}
The screencast:
https://youtu.be/NNDnzrtMLZI
What is wrong?
Full source is available here: https://github.com/tseglevskiy/canvasdemo1/blob/error/app/src/main/java/ru/jollydroid/canvasdemo1/MainActivity.java
回答1:
The Canvas
that Surface.lockCanvas
gives you is not persistent. The moment you call unlockCanvasAndPost
, the contents of the surface buffer are pushed out to the screen. Every time you call lockCanvas
you need to redraw the picture from scratch.
If you want to update the canvas incrementally, you should keep an "off-screen" canvas backed by a Bitmap that you update in response to user actions. Then paint the bitmap to the Surface
canvas.
private void paintStartDot(float x, float y) {
if (mBitmap == null) return; // not ready yet
Canvas canvas = new Canvas(mBitmap);
canvas.drawPoint(x, y, drawPaint);
// draw the bitmap to surface
canvas = surface.lockCanvas(null);
canvas.drawBitmap(mBitmap, 0, 0, null);
surface.unlockCanvasAndPost(canvas);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// good place to create the Bitmap
mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config. ARGB_8888);
// also here we need to transform the old bitmap to new one
}
I'm not sure if you really need a SurfaceView
. You could just extend the View
and override its View.onDraw
method. In that case, call view.invalidate()
to indicate it needs to be redrawn.
See also: Android View.onDraw() always has a clean Canvas
来源:https://stackoverflow.com/questions/36266994/how-to-draw-to-canvas-from-surfaceview