4

I searched the internet for hours and I couldnt come up with a good solution.

I try to scroll text on my UIView from left to right and vice versa. I dont want to use CoreAnimations as I need to be in control over the animation.

The movement follows a sinus curve, 0 to pi or 0->1->0.

What is the best way to implement that custom animation?

What I came up with after some research, is a recoursive algorithm that calls it self and goes through the loop, until done.

- (void) scrollText:(id)sender timeConstant:(float) _timeconstant timeOffset:(NSDate*) _timeoffset direction:(int)_direction
{

float p = [[NSDate date] timeIntervalSinceDate:_timeoffset] / _timeconstant * _direction;   
float ps =  sinf( p * M_PI);


CGSize txtsize = [msg_text sizeWithFont:font];

float offset = txtsize.width / 2;
float screenwidth = self.view.frame.size.width;
float screenheight= self.view.frame.size.height;


int virtualwidth = txtsize.width;
[ivText setFrame:CGRectMake(screenwidth/2 - offset + (virtualwidth / 2 * ps), 100, txtsize.width, txtsize.height)];

//redraw
[[self view] setNeedsDisplay];
//keep going
if (ps * _direction > 0) [self scrollText:self timeConstant:_timeconstant timeOffset:_timeoffset direction:_direction];


}

The problem now is, that the view wont update :( and Im not sure if this is the best approach for this kind of animation.

floohh
  • 79
  • 5
  • I think this deals with the same problem: http://stackoverflow.com/questions/4739748/is-there-a-way-to-make-drawrect-work-right-now – floohh Oct 26 '11 at 02:33

1 Answers1

1

I think your view is not updating because you're never breaking out of the recursion, and so the run loop is never finishing an iteration. A better solution than a recursive method could be to use an NSTimer which fires off your function once every, say, 1/30th or 1/60th of a second using +[NSTimer timerWithTimeInterval:target:selector:userInfo:repeats:].

If you want to keep the recursive structure you have here, you can use -[NSObject performSelector:withObject:afterDelay:] to call your function after a delay. Just use something like 1/60.0 for the delay, and package up any information you need into a dictionary or array to pass to the withObject: parameter.

Either of these methods registers your method with the run loop to be called at a later time. This allows the run loop to start a new iteration, which means UI updates can happen.

Edit: if your string isn't changing during this animation, calculate the text size once and store it in an instance variable. Calculating the size of a string during each call of your method can be expensive.

Zev Eisenberg
  • 8,080
  • 5
  • 38
  • 82