I'm trying to animate (fade in/out) a UILabel and I'm using the following code:
float newAlpha = 0.0;
//TODO:Check if the previous animation has finished
if(answer.alpha==0.0) {
newAlpha = 1.0;
} else if(answer.alpha==1.0) {
newAlpha = 0.0;
}
[UIView animateWithDuration:1.0 animations:^{
answer.alpha = newAlpha;
}];
Where the TODO comment is, I want to check if the previous animation has finished and if it hasn't, exit the method. Is there some way of doing this?
UPDATE #1:
you need a variable in your class:
BOOL _animationFinished;
and then you can use the following way for the animation:
float newAlpha = 0.0;
//TODO:Check if the previous animation has finished
if (_animationFinished == false) return;
if(answer.alpha==0.0) {
newAlpha = 1.0;
} else if(answer.alpha==1.0) {
newAlpha = 0.0;
}
[UIView animateWithDuration:1.0f animations:^{ answer.alpha = newAlpha; _animationFinished = false; } completion:^(BOOL finished){ _animationFinished = true; }];
it must be work.
ORIGINAL
I'm always checking the subject of the animation in this case, like this:
float newAlpha = 0.0;
//TODO:Check if the previous animation has finished
if (answer.alpha > 0.f || answer.alpha < 1.f) return; // it is always good enough for me
// ...or with AND it will cause the same effect:
// if (answer.alpha > 0.f && answer.alpha < 1.f) return;
if(answer.alpha==0.0) {
newAlpha = 1.0;
} else if(answer.alpha==1.0) {
newAlpha = 0.0;
}
[UIView animateWithDuration:1.0 animations:^{
answer.alpha = newAlpha;
}];
If you're using UIView then
[UIView setAnimationDidStopSelector:#selector(animationfinished)];
-(void) animationfinished
{
animationFinished = YES;
}
Use animateWithDuration:animations:completion: method to do your "previous animation", and set a flag in the completion handler to indicate if it's finished or not. Then, check the same flag exactly where you have the TODO comment.
Edit: Example below
-(void) animation1 {
// assume that alpha was 0 and we want the view to appear
[UIView animateWithDuration:1.0 animations:^{
answer.alpha = 1.0;
} completion:^(BOOL finished){
fristAnimationFinished = finished;
}];
}
-(void) animation2 {
float newAlpha = 0.0;
if (!firstAnimationFinished)
return;
if(answer.alpha==0.0) {
newAlpha = 1.0;
} else if(answer.alpha==1.0) {
newAlpha = 0.0;
}
[UIView animateWithDuration:1.0 animations:^{
answer.alpha = newAlpha;
}];
}
Related
I am dragging a view from bottom to top with pre-defined offset positions using pan gesture.
My current implementation is such that the view updates after the gesture has ended. However, I want the view to update along with the finger (gesture is ongoing) and stop at the predefined (next) position when the gesture has ended.
Would appreciate if somebody could point me in the right direction. Thank you.
m_openPercentage = #"30,60";
- (void)onContentViewPanned:(UIPanGestureRecognizer *)gesture
{
CGPoint velocity = [gesture velocityInView:self.view];
NSArray *m_Openpercentage = [m_OpenPercentage componentsSeparatedByString:#","];
NSMutableArray *fullpercentage = [NSMutableArray arrayWithArray:m_Openpercentage];
float diffy = 0.0;
if(([gesture state] == UIGestureRecognizerStateEnded))
{
if(velocity.y < 0)
{
if(m_isfullscreen && ![fullpercentage containsObject:#"100"])
{
[fullpercentage addObject:#"100"];
}
diffy = 1-([[fullpercentage objectAtIndex:counter] floatValue]/100);
CGFloat ypos = self.view.frame.size.height * diffy;
[UIView animateWithDuration:1 delay:0 usingSpringWithDamping:0.5 initialSpringVelocity:0.5 options:0 animations:^{
[self.view setNeedsLayout];
self.view.frame = CGRectMake(0,ypos,self.view.frame.size.width,self.view.frame.size.height);
if(self.view.frame.origin.y==0)
[self showNavigationbar:1];
} completion:^(BOOL finished) {
}];
if(counter<[fullpercentage count]-1)
counter++;
}
else
{
if(counter>0)
{
float diffy = 1-([[fullpercentage objectAtIndex:counter-1] floatValue]/100);
CGFloat ypos = self.view.frame.size.height * diffy;
[UIView animateWithDuration:1 delay:0 usingSpringWithDamping:0.5 initialSpringVelocity:0.5 options:0 animations:^{
self.view.frame = CGRectMake(0,ypos,self.view.frame.size.width,self.view.frame.size.height);
} completion:^(BOOL finished) {
}];
}
else
{
diffy = 1-(m_initialPercentage/100);
CGFloat ypos = self.view.frame.size.height * diffy;
if(self.view.frame.origin.y < ypos)
{
[UIView animateWithDuration:1 delay:0 usingSpringWithDamping:0.5 initialSpringVelocity:0.5 options:0 animations:^{
self.view.frame = CGRectMake(0,ypos,self.view.frame.size.width,self.view.frame.size.height);
} completion:^(BOOL finished) {
}];
}
else
{
[self removeoverlayview];
[self.view removeFromSuperview];
id tmpControllerObj = [parentController getParentController];
[tmpControllerObj view].userInteractionEnabled = YES;
}
}
if((counter-1)>=0)
counter--;
[self showNavigationbar:0];
}
if(![m_Openpercentage containsObject:#"100"] && m_isfullscreen)
[self updatefullview];
}
}
I tried everything, but everytime its the same problem:
i want to move a button for y = 276. when the animation ends, my buttons jumps back to the startposition, but i want that the endanimationposition is the new position, and the button has to stay there, until a new animation is called.
tried with
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1];
CGPoint p = _cell00.center;
p.x += 100;
_cell00.center = p;
[UIView commitAnimations];
[UIView beginAnimations:nil context:nil];
same issue like
[UIView animateWithDuration:1.0 animations:^{
_cell00.frame = CGRectOffset(_cell00.frame, 0, 20);
}];
or
[UIView animateWithDuration:0.5 animations:^{
_cell00.center = CGPointMake(0, 20.0);
}];
EDIT:
I call this Animation with my Button called statisticsBUttonPressed.
- (IBAction)statisticsButtonPressed:(id)sender {
if (statOrGame == 0) {
statOrGame = 1;
}else {
statOrGame = 0;
}
NSLog(#"statOrGame? %d", statOrGame);
[self animateView:(UIButton *)sender];
}
-(void) animateView:(UIButton *)sender {
sender.userInteractionEnabled = NO;
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone)
{ // The iOS device = iPhone or iPod Touch
NSLog(#"IS IPHONE 5");
CGSize iOSDeviceScreenSize = [[UIScreen mainScreen] bounds].size;
if (iOSDeviceScreenSize.height == 568)
{
if (statOrGame) {
[UIView animateWithDuration:1.0 animations:^{
_cell00.frame = CGRectOffset(_cell00.frame, 0, 20);
}];
}
}
}
}
The problem is that you're using auto layout. You can't (just) change the frame of a view that is positioned by auto layout, because what positions the view is its constraints. You need to change the constraints. You can do this at the end of the animation, or you can simply animate the change of constraints.
I have a UITextField that is set to hidden, when I click the search button I want to make it visible but I want to create an animation like a slide-in, is it possible to recreate this effect if i'm using autoLayout?
The code I used for the animation is the current (it creates a fade-in effect):
if(!currentSrcState)
{
_searchField.hidden = NO;
[UIView animateWithDuration:0.3
delay:0.0
options:UIViewAnimationOptionTransitionCurlDown
animations:^ {
_searchField.alpha = 1.0;
}
completion:nil];
currentSrcState = YES;
}
else
{
[UIView animateWithDuration:0.3
delay:0.0
options:UIViewAnimationOptionTransitionCurlDown
animations:^ {
_searchField.alpha = 0;
}
completion:^(BOOL finished){
_searchField.hidden = YES;
}];
currentSrcState = NO;
}
What I want to acheive is that when the _searchField is hidden the constraint gets recalculated in order to move what is under the searchField up
Instead of set the button to hidden, set its alpha value to 0.0 before load the view. Then change your code to:
if(!currentSrcState)
{
[UIView animateWithDuration:0.3
delay:0.0
options:UIViewAnimationOptionTransitionCurlDown
animations:^ {
_searchField.alpha = 1.0;
}
completion:nil];
currentSrcState = YES;
}
else
{
[UIView animateWithDuration:0.3
delay:0.0
options:UIViewAnimationOptionTransitionCurlDown
animations:^ {
_searchField.alpha = 0.0;
}
completion:nil];
currentSrcState = NO;
}
I'm trying to make an animation where the text gets moved to the bottom as it fades out, at the same time it reappears at in the same location as before and does the same animation. here my code:
for (int i=0; i<10; i++)
{
[UIView animateWithDuration:0.5
delay:0.2f
options:UIViewAnimationCurveEaseInOut
animations:^{
productTextLabel.center = CGPointMake(381, 410);
productTextLabel.alpha = 0.0;
productTextLabel.center = CGPointMake(381, 340);
productTextLabel.alpha = 1;
}
completion:^(BOOL fin) {
}];
}
my problem is I am trying to make this animation happen more than one time. I am using a for loop but it only does it once.
You can use the options UIViewAnimationOptionRepeat and UIViewAnimationOptionAutoReverse in the animationWithDuration: method to repeat and reverse the animation automatically.
The whole method will become:
[UIView animateWithDuration:0.5
delay:0.2f
options:UIViewAnimationCurveEaseInOut | UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoReverse
animations:^{
productTextLabel.center = CGPointMake(381, 410);
productTextLabel.alpha = 0.0;
}
completion:^(BOOL fin) {
}];
To cancel the animation you can call
[productTextLabel.layer removeAllAnimations];
Note: You should import QuartzCore to be able to call the removeAllAnimations function.
try this way, it worked for me:
__block void (^fadePart1)() = ^{ productTextLabel.center = CGPointMake(381.f, 410.f); productTextLabel.alpha = 0.f; };
__block void (^fadePart2)() = ^{ productTextLabel.center = CGPointMake(381.f, 340.f); productTextLabel.alpha = 1.f; };
__block void (^fadePart1Finished)(BOOL finished) = ^(BOOL finished) {
if (_willFinishAnimation == false) {
[UIView animateWithDuration:0.5f delay:0.2f options:UIViewAnimationCurveEaseInOut|UIViewAnimationOptionAllowUserInteraction animations:fadePart2 completion:^(BOOL finished) {
if (_willFinishAnimation == false) [UIView animateWithDuration:0.5f delay:0.2f options:UIViewAnimationCurveEaseInOut|UIViewAnimationOptionAllowUserInteraction animations:fadePart1 completion:fadePart1Finished];
}];
}
};
fadePart1Finished(false);
I had a global Boolean _willFinishAnimation; variable, before I set the animation it was false and when I want to finish the effect I set it true, that is it.
I would like to animate my subviews movement when rotating the device, changing the alpha to 0, move the view to the new position and reset the alpha to 1.
Using this code in didRotateFromInterfaceOrientation causes the view to flash and fade very quickly and then reappear. I would like to avoid this behaviour.
[UIView animateWithDuration:kAnimationDuration animations:^{
anObject.alpha = 0.0;
CGRect newFrame = anObject.frame;
newFrame.origin.x = newX;
newFrame.origin.y = newY;
newFrame.size.width = newWidth;
newFrame.size.height = newHeight;
anObject.frame = newFrame;
} completion:^ (BOOL finished){
if (finished) {
anObject.alpha = 1.0;
}
}];
Is there a way around this flashing?
Thanks
Maybe actually animate alpha on completition ? rather than flash it ? :)
[UIView animateWithDuration:kAnimationDuration animations:^{
anObject.alpha = 0.0;
CGRect newFrame = anObject.frame;
newFrame.origin.x = newX;
newFrame.origin.y = newY;
newFrame.size.width = newWidth;
newFrame.size.height = newHeight;
anObject.frame = newFrame;
} completion:^ (BOOL finished){
if (finished) {
[UIView animateWithDuration:kAnimationDuration
animations:^{
anObject.alpha = 1;}
}
}];
Cheers,
Krzysztof Zabłocki