1
votes

I have a uiscrollview that has multiple subviews. They are stacked one after the next with spacing constraints. They, with auto layout, define the uiscrollview's contentsize.

Each view is my "snippet view" - a 100 px view. When a user taps a snippet view, i need to replace it with my "message view" - a much taller view. The message view has an intrinsic content size.

When I replace it, I remove all of my constraints, and then apply them again so they stack all the views on top of each other and the newly added message view gets inserted in the proper order.

This actually works fine, but its not smooth. I'd like to animate this so the snippet is removed, the views below are scooted down to make room for the taller message view, the new message view is added with the origin of the previous snippet, and I animate its frame height to fill the space.

I have code that does this without auto layout and it works well. But its a tremendous amount of layout code and I was hoping to do with auto layout.

Ive tried doing the remove / reapply constraints process, and then putting a layoutIfNeeded in an animation block. The problem is the newly added message view gets added with an origin of 0,0 and then animates down to its proper position, which is not a good effect.

2

2 Answers

1
votes

You need to perform an initial layout pass to get the new view into position first.

Add it as a subview, with constraints to give it the right position (you can pin to the top of the outgoing view for this purpose). Call layoutIfNeeded, then remove and update all of your constraints and perform an animated layout as you are now.

Alternatively, before you do the animated layout, manually set the frame of the incoming view to be the same as the outgoing view. The layout pass will then animate from this instead of CGRectZero. That's probably a much neater solution.

0
votes

Usually you'd add your new constraints, and then animate the application of those constraints, e.g.:

[UIView animateWithDuration:0.4 animations:^{
    [self.view layoutIfNeeded];
}];

That will yield a smoother transition as the new constraints are applied.

If you want to avoid having the new subview start at 0,0 and jump down, you might create a container view (which has constraints to all the other views), and add your new view to that container. So the old "snippet view" would be in that container, you would remove it from that container, put the new one in that container, and then animate the layoutIfNeeded once all the new constraints are in place. That should avoid the effect you describe. (It should also simplify the code because you'll only be mucking about with the constraints that dictate the relationship between the container view and the subviews you add to it, and everything else should be driven from that.)