uiview animateWithDuration cant hide in same toggle method - objective-c

Trying to hide and show a view from a single method but it seems like it should work to show and hide but its instant.
- (void)toggleMyView:(BOOL)show
{
CGRect orig = self.originalMyViewFrame; // original frame of the view
CGRect offScreen = CGRectMake(orig.origin.x, self.view.frame.size.height, orig.size.width, orig.size.height);
if (show) {
self.myView.frame = offScreen; // set off screen
self.myView.hidden = NO; // unide the view
[UIView animateWithDuration:0.5 animations:^{
self.myView.frame = orig; // animate to original position
}];
} else {
[UIView animateWithDuration:0.3 animations:^{
self.myView.frame = offScreen; // animate off screen
} completion:^(BOOL finished) {
self.myView.hidden = YES; // hide when animation finished
}];
}
}
If I remove the hide logic it animates in nicely.
- (void)toggleMyView:(BOOL)show
{
CGRect orig = self.originalMyViewFrame; // original frame of the view
CGRect offScreen = CGRectMake(orig.origin.x, self.view.frame.size.height, orig.size.width, orig.size.height);
if (show) {
self.myView.frame = offScreen; // set off screen
self.myView.hidden = NO; // unide the view
[UIView animateWithDuration:0.5 animations:^{
self.myView.frame = orig; // animate to original position
}];
} else {
self.myView.hidden = YES; // hide when animation finished
}
}
I dont see why adding the hide logic breaks.
Could this be a memory retain cycle problem?

Related

Keep the End Position of Animation

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.

Animate a UITextField when changing from hidden to visible using AutoLayout

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;
}

Interactive UIViewController Transition with new "usingSpringWithDamping:initialSpringVelocity"-animation

I try to implement a interactive custom modal UIViewController transition using the new iOS7 APIs. Everything is working as desired as long as I don't use the new
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay usingSpringWithDamping:(CGFloat)dampingRatio initialSpringVelocity:(CGFloat)velocity options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion
method for animating the transition. It is working fine if I invoke the transition via a button. The problem occurs when the transition is interactive, driven by a GestureRecognzier. If I release my finger the animation is immediately cut of and won't finish. The same code is working if I use
animateWithDuration:delay:options:animations:completion:
instead.
Here is the code which animates the transition:
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext {
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
CGRect fullFrame = transitionContext.containerView.frame;
if (!self.dismissal) {
[transitionContext.containerView addSubview:fromViewController.view];
[transitionContext.containerView addSubview:toViewController.view];
fromViewController.view.frame = fullFrame;
toViewController.view.frame = CGRectMake(0, fullFrame.size.height, 0, 0);
[UIView animateWithDuration:[self transitionDuration:transitionContext] delay:0 usingSpringWithDamping:0.5 initialSpringVelocity:0.5 options:UIViewAnimationOptionTransitionNone animations:^{
//animation
toViewController.view.frame = CGRectMake(0,0, fullFrame.size.width, fullFrame.size.height);
} completion:^(BOOL finished) {
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
}];
} else {
[transitionContext.containerView addSubview:toViewController.view];
[transitionContext.containerView addSubview:fromViewController.view];
fromViewController.view.frame = fullFrame;
[UIView animateWithDuration:[self transitionDuration:transitionContext] delay:0 usingSpringWithDamping:.5 initialSpringVelocity:.5 options:0 animations:^{
fromViewController.view.frame = CGRectMake(0, fullFrame.size.height, fullFrame.size.width, fullFrame.size.height);
} completion:^(BOOL finished) {
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
}];
//This is working fine
// [UIView animateWithDuration:[self transitionDuration:transitionContext]/2 animations:^{
// fromViewController.view.frame = CGRectMake(0, fullFrame.size.height, fullFrame.size.width, fullFrame.size.height);
// } completion:^(BOOL finished) {
// [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
// }];
}
This is the code behind the gesture recogniser:
#pragma mark - Gesture recognition
- (void)handlePan:(UIScreenEdgePanGestureRecognizer *)pgr
{
CGPoint translation = [pgr translationInView:pgr.view];
CGFloat percentage = fabs(translation.x / CGRectGetWidth(pgr.view.frame));
switch (pgr.state) {
case UIGestureRecognizerStateBegan:
self.interactionInProgress = YES;
[self.respondingVC proceedToNextViewController];
break;
case UIGestureRecognizerStateChanged: {
[self updateInteractiveTransition:percentage];
break;
}
case UIGestureRecognizerStateEnded:
if(percentage < 0.5) {
[self cancelInteractiveTransition];
} else {
[self finishInteractiveTransition];
}
self.interactionInProgress = NO;
break;
case UIGestureRecognizerStateCancelled:
[self cancelInteractiveTransition];
self.interactionInProgress = NO;
default:
break;
}
}
It looks like you're using UIPercentDrivenInteractiveTransition. When you call finishInteractiveTransition, UIPercentDriventInteractiveTransition does not call animateTransition.
You should override both updateInteractiveTransition and finishInteractiveTransition to update your view states.
All my attempts to begin an animation block inside an interactive transition have ended in failure. I finally at least got it to finish the animation by calling [self updateInteractiveTransition:1] in finishInteractiveTransition. Otherwise the views will be left in the state they were in and the transition never completes or the transition is treated as completed but your views are in strange places.

CGPoint center animation "nullified" by CGAffineTransform

i'm new to Objective-C and Xcode... I'm following a tutorial that explain how to move a car(a ImageView) to the top of the screen, rotate it, an then back to the bottom of the display.
This is the code:
- (IBAction)testDrive:(id)sender {
CGPoint center = CGPointMake(_car.center.x, self.view.bounds.origin.y + _car.bounds.size.height/2 +100);
[UIView animateWithDuration:3
animations:^ { _car.center = center;}
completion:^(BOOL finished){[self rotate];}];
}
- (void) rotate{
CGAffineTransform transform = CGAffineTransformMakeRotation(M_PI);
void (^animation)() = ^() { _car.transform = transform;
};
void (^completion)(BOOL) = ^(BOOL finished){
[self returnCar];
};
[UIView animateWithDuration:3 animations:animation completion:completion];
}
The problem is that the car moves to the top, but then it's position is resetted at the bottom of the screen, like the center was resetted to the default center value, and only then is rotated.. I can't find a solution, need your help!
When you do an animation, its effects are temporary, and by default they don't actually mutate your layers/views. Typically, you would explicitly write the "end" values into the layers/views in the completion block. You will need to do this for each animation in your "chain" of animations. With your code, I suspect you'd get the desired outcome if you did this:
- (IBAction)testDrive:(id)sender {
CGPoint center = CGPointMake(_car.center.x, self.view.bounds.origin.y + _car.bounds.size.height/2 +100);
[UIView animateWithDuration:3
animations:^ { _car.center = center;}
completion:^(BOOL finished){ _car.center = center; [self rotate];}];
}
- (void) rotate{
CGAffineTransform transform = CGAffineTransformMakeRotation(M_PI);
void (^animation)() = ^() { _car.transform = transform;
};
void (^completion)(BOOL) = ^(BOOL finished){
_car.transform = transform;
[self returnCar];
};
[UIView animateWithDuration:3 animations:animation completion:completion];
}
You'll also want to make a corresponding change in -returnCar.
The idea here is that the animation effects only the "presentation layer" but not the "model layer." If you want the model layer to reflect the "after" state of the animation, you need to explicitly do that.
After smashing my head for hours i found the solution to this problem, that was due to AutoLayout.
This is the working code
self.topConstraint.constant = self.topConstraint.constant-self.topConstraint.constant;
[self.car setNeedsUpdateConstraints]; // 2
[UIView animateWithDuration:3
animations:^{
[self.car layoutIfNeeded]; // 3
}
completion:^(BOOL finished){[self rotate]; }
];
Thanks

Have an object fade in and out of existence

I have a view that sets its hidden when the user taps the main view. I need the view to fade in and out of existence so it looks smoother than just disappearing.
Heres my code so far (It's inside a touches event):
if (!isShowing) {
isShowing = YES;
myView.hidden = YES;
//Needs to fade out here
}
else {
isShowing = NO;
myView.hidden = NO;
//Needs to fade in here
}
I've never had luck with animating hidden. Instead, animate alpha.
Just wrap your code like this:
[UIView beginAnimations:nil context:NULL];
if (!isShowing) {
isShowing = YES;
myView.hidden = NO
}
else {
isShowing = NO;
myView.hidden = YES
}
[UIView commitAnimations];
or simplify it to this:
[UIView beginAnimations:nil context:NULL];
isShowing = !isShowing;
myView.hidden = isShowing? NO : YES;
[UIView commitAnimations];
You might also want to use UIView's setAnimationDuration:, setAnimationCurve:, or setAnimationBeginsFromCurrentState: methods to customize how the view fades in and out.