-1

I am trying to make a native Android version of http://arapaho.nsuok.edu/~deckar01/Zvis.html

So, I made a custom View that draws all the squares needed. Of course, this drawing ends up taking 10s of seconds once the number becomes large enough to make the Canvas start drawing thousands of squares.

Is there a better way to do this? It seems like there is something obvious I am not thinking of doing/using.

The onDraw method of the View is below, in case that helps. Any ideas?

 protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    final int number = mNumber;
    final float tileWidth, tileHeight;

    /*mTileWidth = mWW / (number - 1);
    mTileHeight = mHH / (number - 1);*/

    // make them squares
    if (mWW <= mHH) {
        tileWidth = tileHeight = mWW / (number - 1);
    } else {
        tileWidth = tileHeight = mHH / (number - 1);
    }

    mWhiteTextPaint.setTextSize(48f / 72 * tileWidth);
    mBlackTextPaint.setTextSize(48f / 72 * tileWidth);

    float currX = getPaddingLeft();
    float currY = getPaddingTop();

    for (int i = 1; i <= number - 1; i++) {
        mBackgroundPaint.setColor(getBackgroundColor(i, number));
        canvas.drawRect(currX, currY, currX + tileWidth,
                currY + tileHeight,
                mBackgroundPaint);
        final String text = String.valueOf(i);
        canvas.drawText(text,
                currX + tileWidth / 2 - mWhiteTextPaint.measureText(text) / 2,
                currY + tileHeight * 0.9f, mWhiteTextPaint);
        currX += tileWidth;
    }
    currX = getPaddingLeft();
    currY += tileHeight;

    for (int i = 2; i <= number - 1; i++) {
        for (int j = 1; j <= number - 1; j++) {
            final int num = (j == 1) ? i : (i * j) % number;

            mBackgroundPaint.setColor(getBackgroundColor(num, number));
            canvas.drawRect(currX, currY, currX + tileWidth,
                    currY + tileHeight,
                    mBackgroundPaint);
            final String text = String.valueOf(num);
            if (num == 0) {
                canvas.drawText(text,
                        currX + tileWidth / 2 - mBlackTextPaint.measureText(text) / 2,
                        currY + tileHeight * 0.9f, mBlackTextPaint);
            } else {
                canvas.drawText(text,
                        currX + tileWidth / 2 - mWhiteTextPaint.measureText(text) / 2,
                        currY + tileHeight * 0.9f, mWhiteTextPaint);
            }
            currX += tileWidth;
        }
        currX = getPaddingLeft();
        currY += tileHeight;
    }

    if (mOnDrawFinishedListener != null) {
        mOnDrawFinishedListener.onDrawFinished(number);
    }
}
Eric Cochran
  • 8,414
  • 5
  • 50
  • 91
  • http://developer.android.com/training/custom-views/optimizing-view.html#accelerate – CarCzar Sep 05 '14 at 18:36
  • @CarCzar I tried putting setLayerType(View.LAYER_TYPE_HARDWARE, null); in my View's constructor; it did not help noticeably. – Eric Cochran Sep 05 '14 at 18:37
  • You should probably run your drawing code in a different thread. I know there are ways to do this built in to android, but don't know the names at the current moment. Search through the API, I'm sure you'll find it. – CarCzar Sep 05 '14 at 18:42
  • the larger hint is to only actually draw it once, to an image, and after that just draw the image – Meleneth Sep 05 '14 at 18:42

1 Answers1

2

As @CarCzar already said, you could draw everything in a separate thread into a bitmap and then on the UI thread you only draw that bitmap on the screen. Alternatively you could use OpenGL. That's usually used for more dynamic things like games. The thing is that OpenGL runs in a separate graphic thread and therefore will not block your UI.

SimonSays
  • 10,867
  • 7
  • 44
  • 59