Search code examples
javaandroidandroid-canvasandroid-custom-viewondraw

onTouch calling invalidate onDraw - not smooth


I have a code in my custom view, where if I touch, a circle is drawn. When I move the circle follow along. Code as below

// override onDraw
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    if (circleBounds != null) {
        canvas.drawArc(circleBounds, 360, 360, false, mPaint);
    }
}

// when ACTION_DOWN start touch according to the x,y values
private void startTouch(float x, float y) {
    mPath.moveTo(x, y);
    mX = x;
    mY = y;
    circleBounds.set(mX - mRadius, mY - mRadius, mX + mRadius, mY + mRadius);

    invalidate();
}


//override the onTouchEvent
@Override
public boolean onTouchEvent(MotionEvent event) {
    float x = event.getX();
    float y = event.getY();

    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
        startTouch(x, y);
        break;
    case MotionEvent.ACTION_MOVE:
        startTouch(x, y);
        break;
    }
    return true;
}

When I move slowly, the movement is smooth. But when I move fast, one could feel the flickering. I guess invalidate() happens many time, causing the flickering. Is there a way to make it smoother (reduce the flickering on the drawn circle)?


Solution

  • Invalidate is not your issue, the system has double buffering, and you should not see a flicker. From your code, I can think of 2 way to improve:

    1. in onStartTouch you call mPath.moveTo(). It is not clear why you need mPath, but this path will keep growing and growing and will need more memory
    2. canvas.drawArc is rendered by by CPU (it creates a bitmap and draws the arc into it on every call to onDraw). It would be faster to render yourself the circle once into a bitmap, and draw that bitmap in onDraw. If you keep using the same bitmap, it will be loaded once to the GPU and drawing will be much faster