I have a problem with performance on iPad. I need to drag UIView with animation. It's like self made UIScrollView, but with bigger bounce effect.
I use self made animation cycle with NSTimer (scheduletTimerWithInterval 0.3 sec). On each iteration I move view step by step.
But the problem is that it's freeze time to time. Not too much... but enough to feel.. Do anyone knows any approaches to do following thing in correct way, so it will work as charm?
Thanks in advance!
You should use [UIView beginAnimations] instead of the scheduled timer. For example, to move something over 2 seconds, you could do something like this:
YourView.center = CGPointMake(0,0);
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:2];
YourView.center = CGPointMake(30, 30);
[UIView commitAnimations];
This will move YourView from 0,0 to 30,30 over 2 seconds (that's what the setAnimationDuration is for). So you would have a sequence of these if you wanted to do a bounce effect. You can also be notified when the animation completed by using
[UIView setAnimationDidStopSelector:#selector(somefunction)]
at which point you could kick off another animation in your function "somefunction".
Perhaps the timer causes your problem. The interval of animations should be something like that: 1.0/60.0f
Related
I need to perform 9 animations where each animation starts after previous one. So I have huge gigantic piece of code with UIView animateWithDuration calls. It really looks ugly :) Is there any better options than making 8 additional methods and nesting them?
Core Animation is your friend.
http://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/CoreAnimation_guide/Introduction/Introduction.html
Or you can write all of these 9 steps into one method by using block-based animation method. But it still dosen't look beautiful and iOS 4 is requied.
You can still use the UIView animation or coreanimation and use the delegate call back i.e:
[UIView beginAnimations:#"fadeIn" context:nil];
[UIView setAnimationDuration:0.3];
[UIView setAnimationDidStopSelector:#selector(finishAnimation:finished:context:)];
[UIView setAnimationDelegate:self];
theview.alpha = 1;
[UIView commitAnimations];
then in the finishAnimation method you can call another animation.
I have a custom view that has to track the user's location. I put the following code in touchesBegan, as well as in touchesMoved:
[UIView animateWithDuration:0.2 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
cursorView.center = locationOfTouch;
} completion:^(BOOL finished){}];
It seems fairly straightforward to me. I'd expect the view to always animate to the user's current location, even if that location is changed and the view is still animating (because of the beginFromCurrentState option).
Yet, each animation finishes completely. They don't 'transition' to the new animation, no they finish first, then they start the new animation.
I tried adding this line in touchesMoved:
[cursorView.layer removeAllAnimations];
Doesn't do anything. No animation is cancelled. Any ideas?
with [cursorView.layer removeAllAnimations]; you access the layer of the view but you have set the animation not to the layer but the view directly.
Try:
[UIView beginAnimations:nil context:NULL]
[UIView setAnimationDuration:0.2];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
cursorView.center = locationOfTouch;
[UIView commitAnimations];
and leave out the removeAllAnimations and it should transition from current state.
Looks like this is a derivative of another question you asked that I just answered, but the same idea applies.
You don't need to use blocks to do this. Just wrap your setCenter in a UIView animation. Like this:
[UIView beginAnimations:nil context:NULL]
[UIView setAnimationDuration:0.2f];
cursorView.center = locationOfTouch;
[UIView commitAnimations];
Keep in mind that 0.2 seconds is pretty fast. It may appear to be "jumping" to the position. To confirm, set the duration to something like 2.0 seconds and see if it's animating.
Best regards.
Technically, the view should automatically animate with a default time of 0.25 seconds. That is what the manuals say, however, I'm currently on here because the manuals don't seem to be very accurate regarding animation.
Also, the beginAnimations call is being phased out, you might want to use a CATransaction instead
I have a block of UIView animation code that looks like this:
[UIView beginAnimations:#"pushView" context:nil];
[UIView setAnimationDelay:0];
[UIView setAnimationDuration:.5];
[UIView setAnimationDelegate:self];
[UIView setAnimationWillStartSelector:#selector(animationWillStart)];
view.frame = CGRectMake(0, 0, 320, 416);
[UIView commitAnimations];
The code basically mimics the animation of a ModalView presentation and is tied to a button on my interface. When the button is pressed, I get a long (.5 sec) delay (on iPod Touch...twice as fast on iPhone 3GS) before the animationWillStart: actually gets called. My app has lots going on besides this, but I've timed various points of my code and the delay definitely occurs at this block. In other words, a timestamp immediately before this code block and a timestamp when animationWillStart: gets called shows a .5 sec difference.
I'm not too experienced with Core Animation and I'm just trying to figure out what the cause of the delay is...Memory use is stable when the animation starts and CoreAnimation FPS seems to be fine in Instruments. The view that gets animated does have upwards of 20 total subviews, but if that were the issue wouldn't it cause choppiness after the animation starts, rather than before? Any ideas?
Try it with a single subview or with no subviews at all to make sure the delay is not caused by so many children.
Profile the code in Instruments to see where exactly the code lags. You might get down to some internal Core Animation function call that will hint you what’s going on.
Try the code without the “lot that’s going on” to make sure you’re not stepping on Core Animation’s toes with your other code.
Or, in short: experiment and measure, because conjectures seldom work when optimizing.
In your pasted block, you specify the selector animationWillStart (no colon), but later in your question, you refer to animationWillStart: (with colon). These selectors are not equivalent, so is it possible that your intended selector is never being called on account of this animation, and is being called 0.5 seconds later on account of some other animation?
I have a UIImageView that is displaying a series of pictures as an animation. This part of the project works well.
I want to display a label when the animation ends. Is there an event that the Imageview will trigger when it's animation ends?
Set the duration the animation will go using setAnimationDuration:
At the same time you configure performSelector:withObject:withDelay with the same delay as the duration the animation will go on
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0]; //the animation will last for 1.0s
//some animation code here
[UIView commitAnimations];
[self performSelector:#selector(someMethodToDisplayLabel) withObject:nil afterDelay:1.0];
//someMethodToDisplayLabel will be called after 1.0s
Doesn't look like there is an event/delegate for this. My first instinct would be to calculate the length of the animation yourself, and then set up an NSTimer so that when the animation ends, NSTimer fires displaying whatever you want to display next.
I'm learning Cocoa/Objective-C/iPhone SDK, and as a simple project to apply what I've learned, I wanted to create a simple version of the Simon game of old. Four colored buttons, you're shown a sequence (Red, Green, Blue, Red, etc.) and you have to repeat the sequence back.
I believe I have most of it figured out, save one piece: showing the sequence to the user. Specifically, how to implement the delay between highlighting the button & setting it back to normal after 200ms.
If I sleep in the main run loop, the update doesn't happen properly (even if I explicitly call setNeedsDisplay). If I spawn off a new thread, things get complicated quickly as my class method needs to refer back to UI elements (instant variables).
Any advice?
You can use the +setAnimationStartDate: method on UIView to set up some animations to do this. To ensure that no one presses your buttons during the animation, call -[UIApplication beginIgnoringInteractionEvents] at the start of your animations and -[UIApplication endIgnoringInteractionEvents] at the end.
A written-in-the-text-field example of what I’m talking about:
[[UIApplication sharedApplication] beginIgnoringInteractionEvents];
button1.highlighted = YES;
[UIView beginAnimations:#"" context:nil];
[UIView setAnimationStartDate: CFAbsoluteTimeGetCurrent() + 0.2];
[UIView setAnimationsEnabled:NO];
button1.highlighted = NO;
[UIView commitAnimations];
[UIView beginAnimations:#"" context:nil];
[UIView setAnimationStartDate: CFAbsoluteTimeGetCurrent() + 0.25];
[UIView setAnimationsEnabled:NO];
button2.highlighted = YES;
[UIView commitAnimations];
// etc.
[[UIApplication sharedApplication] performSelector:#selector(endIgnoringInteractionEvents) withObject:nil afterDelay:yourTotalDelay];
"simon" is a very simple MIDI sequencer. therefore I would highly suggest looking into the CoreAudio Framework, in particular the real-time-clock functionality.
gerry3 gives an answer here:
How can I show a sequence of buttons highlighting?
Read the docs for the Core Animation framework.