2

I know this has been discussed over and over again but I can't find a solution to suit my needs.

Scenario: To keep the explanation simple, I have a custom view which displays two images a big one for the background and a smaller one as a Wheel. The user can rotate/scale the background image with onTouch events. He also can rotate the Wheel image to make some operations. Everything is done on a custom View not SurfaceView because I need it to be transparent.

The problem: With onDraw() I always need to check what Rotation/Scale has the background image, scale/rotate it and then draw it. If the background image is smaller, let's say 512x512 the Wheel image rotation is fine. If the background image is bigger, 1280x1707, the wheel image rotation is laggy. So my guess is, manipulation and rotation of a big image in background, for each onDraw() gives me performance issues, when basically the background image should be redrawn only the the user manipulates it.

The rotation is done in something like:

    canvas.save();
    float dx = (maxX + minX) / 2;
    float dy = (maxY + minY) / 2;
    drawable.setBounds((int) minX, (int) minY, (int) maxX, (int) maxY);
    canvas.translate(dx, dy);
    canvas.rotate(angle * 180.0f / (float) Math.PI);
    canvas.translate(-dx, -dy);
    drawable.draw(canvas);
    canvas.restore();

Possible solutions: I could make a new custom View which could only draw the background image and on top of it, put my current View and send touch events, when the case to my background image view. This will allow me to redraw the background image only when needed. Any other ideas ?

Alin
  • 14,809
  • 40
  • 129
  • 218
  • Do you use decoding of `ByteArray` when you get your background image firstly, or it just lies in your /res folder and you set it as background drawable? – teoREtik Nov 17 '11 at 12:50
  • I see a lot of people recreating a new bitmap when they want to rotate it, rather than setting the matrix used to draw the bitmap onto the canvas. If you're not doing that, then try power of 2 sized images. It may be that the device can't handle such large images, but show some code and lets have a looksie. – FunkTheMonk Nov 17 '11 at 12:50
  • No, I just meant, that if the size of image is to large for device you can optimize it, using decoding and `BitmapFactory.Options`. Here is great algorithm, which may allows you to optimize your application perfomance: http://stackoverflow.com/questions/477572/android-strange-out-of-memory-issue/823966#823966 – teoREtik Nov 17 '11 at 13:00
  • @teoREtik I am decoding it using: Drawable.createFromPath(...path...) and I can't scale the image, I need it to have it as the original size – Alin Nov 17 '11 at 13:01

1 Answers1

2

I was having similar performance problems and the solution I found is what I described here. Similar to what you already suggested, basically the background is only drawn once and the custom ImageView handles all transformations on its touch events.

Community
  • 1
  • 1
Narcís Calvet
  • 7,304
  • 5
  • 27
  • 47
  • could you please provide a simple sample code as I can't fully understand the workflow. Thank you. – Alin Nov 29 '11 at 15:26
  • @Alin I'm sorry but I can not provide the code as it's proprietary software but it's based on the schema example I posted at http://stackoverflow.com/questions/6792331/sluggish-zoom-and-scroll-with-gridview-in-android with the modifications on my own reply and what I described in the link I posted here. If it is still not clear don't hesitate to let me know. – Narcís Calvet Nov 30 '11 at 14:19
  • I am not sure I understand what your solution is. I should make a custom framelayout. onSizeChange create a canvas, rotate and scale it, save its content to a bitmap drawable and then set this bitmap as the background ? – Alin Dec 02 '11 at 09:16
  • @Alin yes, exactly. Set the BitmapDrawable as custom FrameLayout's background Drawable (setBackgroundDrawable). – Narcís Calvet Dec 02 '11 at 12:27
  • I'm gonna test it today and see if I manage to get it working. Thanks again. – Alin Dec 05 '11 at 08:16