Friday, March 29, 2024

How to draw countless lines without rendering delay in Android Phone

If you just call the drawing API to draw lines on the screen, you may be comfortable using it when the line number is small, you will see the drawing is flowing smoothly. 

public class DrawView extends View {

    Paint paint = new Paint();

    @Override

    public void onDraw(Canvas canvas) {

        switch (OperationCtrl.nState)

        {

            case CREATE_PATTERN:

                DrawPattern(canvas, alTouchPoints);

                break;

        }

    }

   private void DrawPattern(Canvas canvas, ArrayList<CustomPoint> points)

    {

            ...

        for (int i = 0; i < points.size()-1; i++) 

        {

            lines[lineIndex++] = points.get(i).x;

            lines[lineIndex++] = points.get(i).y;

            lines[lineIndex++] = points.get(i+1).x;

            lines[lineIndex++] = points.get(i+1).y;

        }

        paint.setColor(color);

        paint.setStrokeWidth(thickness);

        canvas.drawLines(lines, paint);

    }

}

I called this method the direct drawing method.

However, when you create hundreds or thousands of lines, the drawing will be so laggy that your app is unable to be enjoyed.

The solution is to use a buffer memory (bitmap) to do all the rendering jobs, then show up once to the user. 

Put thousands of words into one sentence, a simple method can solve the rendering issue.  I called this method the bitmap methodAn additional improvement is every rendering only re-draws new lines compared with the previous bitmap. 

public class DrawView extends View {

    private static Bitmap bufferBitmap = null;

    private static Canvas bufferCanvas = null;

    public static void createBitmap()

    {

        if (bufferBitmap != null) return;

        bufferBitmap = Bitmap.createBitmap(MainActivity.ScreenSize.x, MainActivity.ScreenSize.y, Bitmap.Config.ARGB_8888);

        bufferCanvas = new Canvas(bufferBitmap);

    }

    @Override

    public void onDraw(Canvas canvas) {

        switch (OperationCtrl.nState)

        {

            case CREATE_PATTERN:

                DrawNewTouchPoints(canvas);

                break;

        }

    }

private void DrawNewTouchPoints(Canvas canvas)

    {

        //only draw new lines

       createBitmap();

        if (alTouchPoints.size() <= nLastDrawPoint+1)

        {

            canvas.drawBitmap(bufferBitmap, 0, 0, null);

            return;

        }

        while (alTouchPoints.size() > nLastDrawPoint+1) {

            nLastDrawPoint++;

            int thickness = alDrawThickness.get(nLastDrawPoint);

            int color = alDrawColor.get(nLastDrawPoint);

            int lineIndex = 0;

            float[] lines = new float[4];

            lines[lineIndex++] = alTouchPoints.get(nLastDrawPoint-1).x;

            lines[lineIndex++] = alTouchPoints.get(nLastDrawPoint-1).y;

            lines[lineIndex++] = alTouchPoints.get(nLastDrawPoint).x;

            lines[lineIndex++] = alTouchPoints.get(nLastDrawPoint).y;

            paint.setColor(color);

            paint.setStrokeWidth(thickness);

            bufferCanvas.drawLines(lines, paint);

        }

        canvas.drawBitmap(bufferBitmap, 0, 0, null);

    }

}

With this implementation, the playback is satisfied as expected. For example, drawing 1100 lines with the same speed, the direct drawing method took 55 seconds, while the bitmap method took 18 seconds as designed.

My app DoodleStory using the bitmap method was published in early 2024: https://play.google.com/store/apps/details?id=com.tongs.doodlestory



You can try it out to see the performance. The source codes can be found in GitHub.

My other Android Apps (still available as of today):

FunPatternWifi: Users in the same WiFi network can play this game, one creates a pattern, and then others can observe similar patterns and guess the right one. Source codes are available in GitHub.

Pattern Creation and Guess: this is the single-user version of FunPattern. The user creates one pattern, and then the app generates a few and shows animation on the screen for the user to guess.

Location Alarm and Measure: this app will monitor the current location, and give an alarm when entering or leaving a certain range of the preset location. It can also easily measure the distance between locations. Source codes are available in GitHub.

Hit and Solve Maths: this app shows a block on the screen randomly, the user can try to hit and do a maths calculation for fun.




How to draw countless lines without rendering delay in Android Phone

If you just call the drawing API to draw lines on the screen, you may be comfortable using it when the line number is small, you will see th...