views:

521

answers:

2

I am pondering the alternatives on how to scroll an "infinite", scale-like, control in android. The simple idea is to redraw the entire view on each scroll movement, but somehow it doesn't seem like the proper way. It is possible to draw the contents before-hand, but I have no clue how wide I should make the view in the first place, and what happens when the user scrolls to the end of the view? I guess I need to extend the view towards that direction.

Should I go towards programatically adding (and removing) chunks of view to a linear layout? It would be great to hear what experiences are out there regarding drawing this kind of long-scrolling custom control.

Thanks /Erik

+1  A: 

use an offscreen buffer the size of your control.

at first do it the simple way. Draw the entire offscreenbuffer scrolled to the correct position. When ready blit it to the actual screen.

If this is too slow, try to optimize it by not redrawing the entire offscreenbuffer but by making a vertical split: (I'm only talking about a horizontal scroll movement here for now to make the concept easier to grasp. But this method applies to 8 way scrolling as well)

this is somewhat tricky to implement (that's why I suggested the simple approach first), but try to imagine a paper with picture on it, and the left side you wrap around and glue it to the right side (so you get a tube). This way you can scroll the paper indefinitely (by rotating the tube around it's y axis).

similarly you can do the same with the offscreen buffer.Prepare the offscreen buffer by drawing the complete contents on it.

now to scroll to the right you basically split the offscreen buffer in 2 (by way of this vertical split (just like the paper in the example where the glue was)). suppose you scroll 10 pixels to the right, what you do is:

  • copy the right hand side of the split (located at pixel 10) to pixel 0 of your control. (so the whole region from (10, 0) - (width - height) to: (0,0)
  • then copy the left hand side of the split: pixel 0 to 10 to pixel width-10. so: (0,0)-(10,height) to (width-10, 0)

before you do this ONLY redraw the pixels which have been to be altered (in this case 10 pixels since we scrolled 10 pixels). All other pixels are still identical and don't need redrawing.

You'll have to draw this out on a paper yourself to really understand it. It is a quite common technique with game development on platforms where resources are limited (mobile phones etc).

p.s. scrolling in all directions can be achieved in the exact same way (although it's even harder to get right) ;^)

Toad
Thanks for this nice algorithm. It seems to be possible to adapt this to behave just as I'd like, but it also seems to require more detailed development than the component suggested by Reflog. Thus I'll make that the answer.
ErikR
+1  A: 

if you are working with list/grid or anything that uses Adapter for data, you can use a most excellent class written by CommonsWare and available here:

http://github.com/commonsguy/cwac-endless

it was was specifically for this purpose

Reflog
This looks promising, but I haven't looked into the details of the component. The demo seems to pause and show a progress thingy while retrieving additional views. I'd like to make the control feel more seemless by rendering the views that are likely to be scrolled on screen a little while before the are actually needed. Do you know if this is possible with this component. The documentation is a bit brief.
ErikR