2
votes

I am probably doing something extremely stupid but I cannot figure out why this does not work.

I am trying to perform a simple UIView block animation but have run into trouble. I have recreated in a test project.

I have a view on a View controller, when I press the button, I create a new view and set its frame to be out of the current view (above it). I want to animate the transition so that the view currently on the screen moves downwards out of the view as the new one above it comes down to take its place.

Here is the code which is hooked up to the button, the original view is hooked up as self.view1

- (IBAction)buttonPressed:(id)sender {

    UIView *view2 = [[UIView alloc] init];
    view2.backgroundColor = [UIColor blueColor];
    float offScreenY = 0 - self.view1.frame.size.height;
    CGRect offScreenRect = CGRectMake(0, offScreenY, self.view1.frame.size.width, self.view1.frame.size.height);
    view2.frame = offScreenRect;
    [self.view addSubview:view2];

    float oldY = self.view1.frame.origin.y + self.view1.frame.size.height;
    CGRect oldRect = CGRectMake(0, oldY, self.view1.frame.size.width, self.view1.frame.size.height);

    [UIView animateWithDuration:0.5 animations:^{
        self.view1.frame = oldRect;
        view2.frame =  CGRectMake(0, 0, self.view1.frame.size.width, self.view1.frame.size.height);
    }];
}

This just animates view2 down and does not animate view 1.

If I do not add view 2 as a subview and only put view1's frame change in the animation block then view1 animates correctly.

BUT they will not work together!

Why is this?

2
thats probably because oldRect is the same as self.view1.frame. Print both values and you will see whats happeningpdrcabrod
Tried that exact same code and it works fine here. There must be something else that you didn't show here...omz

2 Answers

1
votes

This is a classic symptom of having autolayout turned on. If you animate frame, it works, but as soon autolayout reapplies the constraints on the view, view1 will return to its original location. By adding view2, iOS automatically reapplies autolayout constraints immediately and your view1 therefore won't move.

Bottom line, don't use autolayout and try to animate frame properties directly. Two solutions:

  1. The easy solution is to turn off autolayout. Go to IB, select the "File inspector" and uncheck the "Use Autolayout" button:

    enter image description here

  2. If you want to keep autolayout on, you shouldn't be animating by changing the frame properties directly. You would animate by change the layout constraint constants. This has been answered elsewhere on S.O., but if you need guidance on that approach, let me know.

    The basic idea, though, is to create an IBOutlet for your top constraint for view1 called, say, view1TopConstraint, and then in your animation block you can say

    self.view1TopConstraint.constant += self.view1.frame.size.height;
    [self.view layoutIfNeeded];
    

    For this to work, though, you'd have to be careful about your other constraints on view1 (e.g., have a height constraint, have no bottom constraint or if you have one, lower its priority, etc.). This can be a hassle the first time you do it, but you'll quickly get the hang of animating by changing constraints.

    But, then again, if you're using constraints, you probably shouldn't be defining view2 by its frame, but probably defining constraints for that, too.

0
votes

In this case it is better for you to have a container view.

Add view1 and view2 inside this container accordingly. Container's some part will be in the screen and container's frame size will be double of the size of a view. Animate the container, so the other two views will be animated accordingly..