8

I am attempting to make an image view (logo below) slide upwards by 100 pixels. I am using this code, but nothing happens at all:

[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:3];
logo.center = CGPointMake(logo.center.x, logo.center.y - 100);
[UIView commitAnimations];

This code is in the viewDidLoad method. Specifically, the logo.center = ... is not functioning. Other things (like changing the alpha) do. Maybe I'm not using the right code to slide it upwards?

jscs
  • 63,694
  • 13
  • 151
  • 195
Wes Cossick
  • 2,923
  • 2
  • 20
  • 35
  • In the viewDidLoad method. Sorry about that! – Wes Cossick Jan 07 '13 at 04:08
  • 1
    Are you using autolayout? – Rob Jan 07 '13 at 04:15
  • Agreed with Rob, from just the code given in your example this appears to be an issue with Auto Layout getting in the way of your animation. If you're using Auto Layout, you'll have to animate the constraints instead of explicitly setting the frame. – sudo rm -rf Jan 07 '13 at 04:29
  • I think I am, though I'm not exactly sure how to tell. If so, how would I go about animating the constraints? – Wes Cossick Jan 07 '13 at 04:46

2 Answers2

41

For non-autolayout storyboards/NIBs, your code is fine. By the way, it's now generally advised that you animate using blocks:

[UIView animateWithDuration:3.0
                 animations:^{
                     self.logo.center = CGPointMake(self.logo.center.x, self.logo.center.y - 100.0);
                 }];

Or, if you want a little more control over options and the like, you can use:

[UIView animateWithDuration:3.0
                      delay:0.0
                    options:UIViewAnimationCurveEaseInOut
                 animations:^{
                     self.logo.center = CGPointMake(self.logo.center.x, self.logo.center.y - 100);
                 }
                 completion:nil];

But your code should work if you're not using autolayout. It's just that the above syntax is preferred for iOS 4 and later.

If you're using autolayout, you (a) create an IBOutlet for your vertical space constraint (see below), and then (b) you can do something like:

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    static BOOL logoAlreadyMoved = NO; // or have an instance variable

    if (!logoAlreadyMoved)
    {
        logoAlreadyMoved = YES; // set this first, in case this method is called again

        self.imageVerticalSpaceConstraint.constant -= 100.0;
        [UIView animateWithDuration:3.0 animations:^{
            [self.view layoutIfNeeded];
        }];
    }
}

To add an IBOutlet for a constraint, just control-drag from the constraint to your .h in the assistant editor:

add IBOutlet for vertical constraint

By the way, if you're animating a constraint, be sensitive to any other constraints that you might have linked to that imageview. Often if you put something right below the image, it will have its constraint linked to the image, so you may have to make sure you don't have any other controls with constraints to your image (unless you want them to move, too).

You can tell if you're using autolayout by opening your storyboard or NIB and then selecting the "file inspector" (the first tab on the right most panel, or you can pull it up by pressing option+command+1 (the number "1")):

autolayout on

Remember, if you planning on supporting pre-iOS 6, make sure to turn off "autolayout". Autolayout is an iOS 6 feature and won't work on earlier versions of iOS.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • Using a constant of -50 will put the view off the top of the screen. What you want is the original constant value minus 50. – rdelmar Jan 07 '13 at 05:30
  • @rdelmar Quite right. I presumed that he was moving it off the screen, but clearly he should just change the constant to be whatever it was supposed to be. I've tweaked the code according. – Rob Jan 07 '13 at 05:45
  • Do you know why, if you do this with a button, the title animates from outside of the button to its proper place? I've noticed this before in some of my animation experiments, and it doesn't make sense to me -- I assume that any constrains for the title would be internal to the button itself, and shouldn't be changing. – rdelmar Jan 07 '13 at 05:55
  • To add to the weirdness, if I have another button in the view, that I'm not animating, its title also animates. It looks like the button title might be starting from a location of 0,0 in the button's frame like it lost its origin. This doesn't happen if I put your code in viewDidAppear. – rdelmar Jan 07 '13 at 05:59
  • @rdelmar Agreed. Yes, that is strange. I agree that moving that code to `viewDidLoad` works more like one would have expected, so I've again adjusted my code. Constraints-based operations defy intuition at times... – Rob Jan 07 '13 at 06:22
  • Thanks a lot! the explanation is really good! really helped me – YYfim Jun 05 '14 at 13:42
  • for other new folks (like me). i needed to add all the auto layout constraints, then answer above worked great (when i added only vertical space constraint uiview did not animate and code did not show error, but storyboard showed error/warnings about constraints). – tmr Sep 17 '14 at 23:51
  • Thanks: [self.view layoutIfNeeded]; was the part I did wrong (layoutContraintsIfNeeded wasnt really working) – Helge Becker Oct 21 '14 at 07:34
  • Amazing!! Thanks a lot..i didn't know I can take IBOutlet for NSLayoutConstraints. Thanks :) – nithinreddy Apr 06 '15 at 04:39
  • This seems to work also for "Center Y Alignment" (center vertically) constraints, not only "Vertical Space" (constant to top). Thanks! Also, for some reason the problem does not seem to arise in iOS 7: Animating the frame instead of the constraints, and not calling `layoutIfNeeded()` seems to work perfectly (even on views with autolayout). – Nicolas Miari Jul 20 '15 at 04:47
-1

have u try

logo.frame = CGRectMake(logo.frame.origin.x, logo.frame.origin.y - 100,logo.frame.size.width,logo.frame.size.height)
Yogesh Suthar
  • 30,424
  • 18
  • 72
  • 100
Patrick.Ji
  • 37
  • 3