I am begining to use UIView animation. And can't get such code working properly. Here is what i have
if(_Language.hidden == true)
{
[UIView animateWithDuration:1.0
delay:0.0
options:UIViewAnimationCurveEaseInOut
animations:^ {
_Language.alpha = 1.0;
}
completion:^(BOOL finished) {
_Language.hidden = false;
}];
}
else
{
[UIView animateWithDuration:1.0
delay:0.0
options:UIViewAnimationCurveEaseInOut
animations:^ {
_Language.alpha = 0.0;
}
completion:^(BOOL finished) {
_Language.hidden = true;
}];
}
This code works in such way. Hide animation works as expected. But show animation just waits 1 sec, and pops the object without any transition. Can anyone tell me what I am missing here?
You are changing the hidden attribute to true only after the animation is over, so it doesn't appear until the animation is completed. you should do it before the animation begins :
if(_Language.hidden == true)
{
_Language.hidden = false;
[UIView animateWithDuration:1.0
delay:0.0
options:UIViewAnimationCurveEaseInOut
animations:^ {
_Language.alpha = 1.0;
}];
}
Your _Language.hidden is set as true and hence when it is animating, nothing will appear on the screen. You need to make it visible before animating. Set the hidden property to false and then show the animation. The reverse will work only for hiding when you add it in completion block.
_Language.hidden = false;
[UIView animateWithDuration:1.0 ...
and remove it from completion block,
completion:^(BOOL finished) {
}];
Related
This is a continuation of this question
CGRectMake : How To Calculate X and Y For UIPickerView Animation?
answered by https://stackoverflow.com/users/2315974/danypata
I have a picker view that I want to animate on and off screen on a button press and using the code in the previous question/answer I have got it to animate on screen the first time the button is pressed.
the second tome the button is pressed it just disappears and then the third time it is pressed it animates to the wrong place...please help
the code
if (self.pickerSort.hidden == NO) {
[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
self.pickerSort.frame = CGRectMake(0,self.view.frame.size.height
+ self.pickerSort.frame.size.height,-self.pickerSort.frame.size.width,-self.pickerSort.frame.size.height);
}
completion:^(BOOL finished) {
}];
self.pickerSort.hidden = YES;
// [self performSelector:#selector(hidePicker) withObject:nil afterDelay:1];
} else if (self.pickerSort.hidden == YES) {
self.pickerSort.hidden = NO;
[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
self.pickerSort.frame = CGRectMake(0 ,
self.view.frame.size.height
- self.pickerSort.frame.size.height,
self.pickerSort.frame.size.width,
self.pickerSort.frame.size.height);
}
completion:^(BOOL finished) {
}];
[self.view bringSubviewToFront:self.pickerSort];
Behavior in images - button press animates onto screen beautifully
Second Press it disappears with no animation
Third Press it animates to here
Any help would be great...functionality I am looking for is how to put the picker view back on an animation so the 3rd press is the same as the first
Please try to use the below code.
self.pickerSort.hidden = NO;
NSTimeInterval duration = 0.5;
[UIView animateWithDuration:duration
delay:0
options:UIViewAnimationOptionCurveLinear
animations:^{
CGRect pickerFrame = self.pickerSort.frame;
// currently picker is off the screen, show it.
if (pickerFrame.origin.y == self.view.frame.size.height) {
// set frame to show picker
pickerFrame.origin.y = self.view.frame.size.height - self.pickerSort.frame.size.height;
} else {
// set frame to hide picker
pickerFrame.origin.y = self.view.frame.size.height;
}
self.pickerSort.frame = pickerFrame;
}
completion:^(BOOL finished) {
self.pickerSort.hidden = YES;
}];
After playing around with this and learning the ins and outs of frames and CGRects, I achieved this by using the following code
if (pickerSort.hidden == YES) {
[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
pickerSort.hidden = NO;
visualEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
[self.tableStations addSubview:visualEffectView];
pickerSort.frame = CGRectMake(0,0,originalPickerFrame.size.width,originalPickerFrame.size.height);
visualEffectView.frame = CGRectMake(0,0,originalPickerFrame.size.width,originalPickerFrame.size.height - 64);
}
completion:^(BOOL finished) {
self.navigationController.navigationItem.leftBarButtonItem.enabled = NO;
}];
}
else
{
visualEffectView.hidden = YES;
[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
pickerSort.frame = CGRectMake(0,-originalPickerFrame.size.height,0,0);
}
completion:^(BOOL finished) {
self.navigationController.navigationItem.leftBarButtonItem.enabled = YES;
pickerSort.hidden = YES;
}];
}
I set the original frame size in viewDidLoad like so
pickerSort = [[UIPickerView alloc]initWithFrame:CGRectMake(0.0, 0.0, self.view.frame.size.width, self.view.frame.size.height)];
originalPickerFrame = pickerSort.frame;
pickerSort.frame = CGRectMake(0,-originalPickerFrame.size.height,0, 0);
Hope this can help somebody in the future
I want to animate the text of a UILabel so that it shows one text for a couple of seconds and after that fades into a default text.
I'm currently using the following code:
-(void)tapOnBalance:(id)sender{
[UIView animateWithDuration:1.0 delay:0.0 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
cell.amountLabel.text = #"Hola!";
} completion:nil];
// Pause the function - act as a 'delay'
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:3]];
[UIView animateWithDuration:1.0 delay:0.0 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
cell.amountLabel.text = #"Hallo!";
} completion:nil];
}
This works, but the [NSRunLoop currentRunLoop] is pausing the entire app, blocking everything for 3 seconds.
How do I get rid of the block on the main thread and still get the same result?
A simple fade (not a cross-fade) can go like this:
// change a label's text after some delay by fading
// out, changing the text, then fading back in
- (void)fadeLabel:(UILabel *)label toText:(NSString *)toText completion:(void (^)(BOOL))completion {
[UIView animateWithDuration:0.2 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
label.alpha = 0.0;
} completion:^(BOOL finished) {
label.text = toText;
[UIView animateWithDuration:0.2 delay:0.0 options:UIViewAnimationOptionCurveEaseIn animations:^{
label.alpha = 1.0;
} completion:completion];
}];
}
// simpler signature that can be done on a perform
- (void)changeLabelText:(NSString *)toText {
[self fadeLabel:self.myLabel toText:toText completion:nil];
}
// set the label to something, then change it with a fade, then change it back
self.myLabel.text = #"text";
[self performSelector:#selector(changeLabelText:) withObject:#"hola!" afterDelay:4];
[self performSelector:#selector(changeLabelText:) withObject:#"text" afterDelay:8];
You could also nest the calls' completion blocks (and add a delay param) to do something similar without the performs. To do a cross-fade, apply a similar technique with two labels (that have the same frame) where one's alpha is zero and the other's alpha is one.
I have a background UIImageView which is constantly animating with this code that gets called at the end of ViewDidAppear:
- (void)beginBackgroundAnimation
{
[UIView animateWithDuration:45
delay:0
options:UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse
animations:^{
_background.frame = CGRectMake(-_background.frame.size.width + self.view.frame.size.width,
_background.frame.origin.y,
_background.frame.size.width,
_background.frame.size.height);
}
completion:nil];
}
The problem is, when I perform another animation, such as this:
[UIView animateWithDuration:delay animations:^{
registerRowView.alpha = 1;
registerRowView.frame = newFrame; // this line kills the animation
}];
The background animation resets to it's original state and stops animating..
Thank you in advance!
Try this:
Keep a bool variable globally like: BOOL isFirstAnimationCompleted; and set it false in the starting of the first animation.
[UIView animateWithDuration:45
delay:0
options:UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse
animations:^{
_background.frame = CGRectMake(_background.frame.size.width + self.view.frame.size.width,
_background.frame.origin.y,
_background.frame.size.width,
_background.frame.size.height);
}
completion:^(BOOL finished) {
if(finished) {
isFirstAnimationCompleted = finished;
}
}];
Check while the user wants to perform the second animation like:
if(isFirstAnimationCompleted) {
[UIView animateWithDuration:delay animations:^{
registerRowView.alpha = 1;
registerRowView.frame = newFrame; // this line kills the animation
}];
}
I am trying to animate one of my image form bottom to Top of my screen , for that i am implementing an animation that the current width and height of image will become half during the transition stage and will take its original size once animation completes.
The issue is once the 1st animation is done it hold's for a while and then starts another animation , i want a smooth animation .
Here is the code :
[UIView animateWithDuration:1.0
delay:0.5
options:UIViewAnimationOptionTransitionCurlUp
animations:^{
[_myImageView setFrame:CGRectMake(20.0, 220.0, currentframe.size.width/2, currentframe.size.height/2)];
} completion:^(BOOL finished)
{
if (finished)
{
[UIView animateWithDuration:1.0
delay:0
options:UIViewAnimationOptionBeginFromCurrentState
animations:^{
[_myImageView setFrame:CGRectMake(20.0, 20.0, currentframe.size.width, currentframe.size.height)];
} completion:^(BOOL finished) {
if (finished) {
NSLog(#"2 nd log ");
}
}];
NSLog(#"animation fisnished !!");
}
}];
What should be done ?
try this:
[UIView animateWithDuration:1.0
delay:0
options:UIViewAnimationOptionCurveLinear// use CurveLinear option
animations:^{
} completion:^(BOOL finished) {
}];
I have an forever animation, but I want to stop it at some point I tried removeAllAnimations but it did not work.
Here is my code.
[self.backgroundImageView.layer removeAllAnimations];
-(void)animateToLeft{
if(isInCenter){
[UIView animateWithDuration:10.0f animations:^{
backgroundImageView.frame = CGRectMake(kLeftX, 0, kBackgroundWidth, kBackgroundHeight);
}completion:^(BOOL finished) {
[self animateToRight];
}];
isInCenter = NO;
}
else{
[UIView animateWithDuration:20.0f animations:^{
backgroundImageView.frame = CGRectMake(kLeftX, 0, kBackgroundWidth, kBackgroundHeight);
}completion:^(BOOL finished) {
[self animateToRight];
}];
}
}
-(void)animateToRight{
[UIView animateWithDuration:20.0f animations:^{
backgroundImageView.frame = CGRectMake(kRightX, 0, kBackgroundWidth, kBackgroundHeight);
}completion:^(BOOL finished) {
[self animateToLeft];
}];
}
This will not work in your situation.
Because [self.backgroundImageView.layer removeAllAnimations]; this will remove all layer animation which already have added by [self.backgroundImageView.layer addAnimation:/*CABasicAnimation should added here*/];
You can stop this cycle by set boolean variable in completion, then check with boolean variable.
Use a boolean value and if that is set, don't do the next animation -- also cancel pending ones..
e.g.
#interface MyClass () {
BOOL cancelAll;
}
#implementation MyClass
-(void)cancelAnimation {
self.imageView.layer removeAllAnimations]; //!
cancelAll = YES;
}
-(void)animateToLeft{
if(cancelAll)
return;
...
}
-(void)animateToRight{
if(cancelAll)
return;
...
}