UIView with CATransform3D inside a UITableViewCell = Choppy Scrolling
Asked Answered
X

2

4

I'm using a custom UITableViewCell, into which I am placing a subclassed UIView (within contentView, natch). The UIView in question displays a directional arrow and two lines of supporting text.

The arrow is displayed by means of a layer with a background color and an arrow-shaped mask. The background color changes to one of two possibilities depending on the direction the arrow is pointing.

The view receives a NSNotification whenever it needs to update the arrow (based on, but not identical to, the current heading - each cell and view is different). When it receives notice, the view calls a private method to perform a transform. This animates the arrow layer, effectively rotating it around its center to a new direction, like so:

    // Update layer BG color, then ...

    [UIView setAnimationBeginsFromCurrentState:YES];
    CATransform3D transform = CATransform3DMakeRotation(DegreesToRadians(locationDirection), 0, 0, 1);
    _arrowLayer.transform = transform;

(n.b.: _arrowLayer is for internal use only, and is not exposed through a property.)

There is also a property on the UIView to set info used to create the supporting text. When this is changed, setNeedsDisplay is invoked, the drawRect: method makes the calculations and draws the resulting text.

That's all well and good. However, there is one major problem I'm encountering:

Scrolling the table view at the same time the arrows are animating results in some major league choppy scrolling, often to the point of the scrolling stopping short! Even when this is the only view in contentView (in the name of minimal test cases), it doesn't matter.

If the device is not moved, scrolling is moderately acceptable, but still open to improvement.

I'm hopeful that I'm simply making a fundamental error (Don't use drawRect:? Do the transform some other way? None of the above?)

Thanks in advance for any clues/advisement!

UPDATE 4 Oct 2011: I tried having the UITableViewController watch UIScrollViewDelegate (per the UIScrollView programming guide) for when scrolling starts/stops, then each directional arrow view asks its delegate (the Table VC in this case) if it's OK to animate. This doesn't help much either though. If animation is in progress, we're out of luck. Perhaps NSNotification is in order, with the directional arrow view looking for a certain notification. (That sounds a bit backwards though, doesn't it? Giving other objects a notification that they can send out? Hmm.)

Xylo answered 14/9, 2011 at 16:49 Comment(0)
C
0

Try something like this:

self.layer.shouldRasterize = YES;

I'm not sure which layer (or layers) should set this property, but I've often faced the problem of animation being jerky, which problem is fixed by setting shouldRasterize.

Cottar answered 5/10, 2011 at 17:50 Comment(5)
I'll give that a try - thank you! Didn't even think about that one. In my case, I s'pose I would set the layer being rotated. Worth a shot.Yellowweed
Oh, interesting. As soon as you mentioned shouldRasterize, I found this: #3248701Yellowweed
Update: If I understand correctly, shouldRasterize is for offscreen rendering, but the CALayer that I'm rotating is always in view, plus I'm using masks, and rasterization happens before the mask kicks in. Danger Will Robinson?Yellowweed
Yes, danger, definitely. I do not pretend to understand how shouldRasterize works - in every case where I've used it to fix jerky animation, it seems like logically it should have exactly the opposite effect.Cottar
No worries. It was worth a shot!Yellowweed
U
0

The trick for performant scrolling is to use CoreGraphics instead of CoreAnimation. The explanation can be found here:

http://blog.atebits.com/2008/12/fast-scrolling-in-tweetie-with-uitableview/

Here is another StackOverflow Question: Tricks for improving iPhone UITableView scrolling performance?

So in this example, I would try to avoid the arrow mask and draw it with CG

Urea answered 5/10, 2011 at 17:59 Comment(1)
Aye, I'm already using Loren's technique elsewhere in the cell (for the supporting text). As I understand it, it's not that we use CoreGraphics "instead of" CoreAnimation. It's that CoreAnimation will scroll smooth-as-glass the more you do your own drawing. (Apple has a table view cells demo which shows a variety of techniques here.) ... all of which leads me straight back to my question: Can you have an independently animated object (which has nothing to do with the scrolling of a table view cell) and have it peacefully coexist?Yellowweed

© 2022 - 2024 — McMap. All rights reserved.