I’m trying to get a handle on ScrollView performance, and why I’m seeing performance deterioration displaying huge content.
My app currently runs Landscape only, and displays ~30pt Hebrew text with diacritical marks.
The texts are displayed in vertically moving scrollview, based on primo.cerar’s widgetsFix code discussed and found in the http://forums.coronalabs.com/topic/42131-in-g2-scrollview-is-not-that-smooth/page-2.
On an iPhone 5, the total text sizes range from 3 screen heights to 60 screen heights. Every word has from one to three diacritical marks. Previous versions of my app displayed each word as its own group object in black characters so that I can detect touch events on the word and to create background highlight rectangles and text color changes that dynamically change color to show the word that currently being referenced and its properties.
In order to draw the diacritical marks in various colors to emphasize special aspects, I’m now drawing partial words and each diacritical mark as its own object. To further stress the system, in some cases, I’m drawing each mark five times to create an inset effect. It does look great on screen, but is seriously hogging performance (as could be expected).
The number of objects ending up on the screen can range from a couple of hundred objects and their related words to a maximum of nearly 20,000 multicolored objects for displaying 2700 words.
At some number of objects, seemingly depending on the specific iOS device and its processing power, the scroll view’s behavior begins to deteriorate severely:
Touch the screen, then slowly move finger up, then release: scrollview does not move until I release.
With the scrollview from primo.cerar’s widgetsFix code scrolling a huge numbers of objects, flicking does not work at all. Detection of flicking is handled in the frame event handler. It appears that at some large numbers of objects or greater being moved, the frame event handler never (or rarely) gets triggered. Changing frame rate from 30 to 60 fps seems to not make a difference with large texts, and could make it work worse for medium size texts, if the problem is that the system has too much to do between frames.
I did get flicking to work in a barely acceptable manner by moving some of the flick-detecting code into the touch handler. I haven’t found a way to get slow scrolling to follow my finger. Putting a Print in the touch handler shows me that _view.y is being set during the entire time my finger is moving; the rendering of the move doesn’t happen until I stop moving my finger. With small texts, everything works smoothly.
Programmatic ScrollTo (using TransitionTo) works without any perceptible delays.
It really seems that it’s taking the system too long to calculate what to do with all those objects to be able to smoothly render those appearing in the window of the screen.
My Mac and PC software does the same type of display using a huge canvas, but it seems the canvas “equivalent” here, Snapshots, can’t be instantiated large enough to take my entire text.
I’ve considered adding and removing text rows like in TableView widget, but my text rows and their borders are not simple rectangles, so the code to manage this won’t be simple, and I’m not sure I can keep up with rapid flicks. This may ultimately be the way to handle this problem.
I’m wondering if there’s a way to pre-render (on the fly) and aggregate my multicolored text object groups so that the scrollview has way fewer objects to manage. I do need to detect touch on words, but can calculate what’s being touched from location. I do need to dynamically alter the text and background color of highlighted words perhaps once every 1/2 second, but that involves changing the word that was highlighted and then the word that will be highlighted; the other 2700 words remain static.
Thoughts on this tough subject will be greatly appreciated.
-Tom