UIView animation animates position but not width

I am trying to convert a UISearchBar like in Mobile Safari: tap the search field and it grows when the location field is compressed.

My current animation, to change the width and position of the search field, only animates the position: before it moves to the right place, it just jumps out to the desired width. Here is my code:

[UIView beginAnimations:@"searchGrowUp" context:nil]; [UIView setAnimationCurve:UIViewAnimationCurveEaseIn]; [UIView setAnimationDuration:0.5f]; [UIView setAnimationDelegate:self]; CGFloat findFieldWidth = findField.frame.size.width; CGFloat urlFieldWidth = urlField.frame.size.width; CGRect findFieldFrame = findField.frame; CGRect urlFieldFrame = urlField.frame; findFieldFrame.origin.x = findFieldFrame.origin.x - 150.0f; findFieldFrame.size.width = findFieldWidth + 150.0f; urlFieldFrame.size.width = urlFieldWidth - 150.0f; urlField.frame = urlFieldFrame; findField.frame = findFieldFrame; [UIView commitAnimations]; 

I modified this code a bit to introduce it here, but I hope this makes sense.

Any guesses as to why this is happening will be appreciated!

Cheers, Aaron.

+7
cocoa-touch core-animation uiview
source share
4 answers

I realized this thanks to this post: Resizing a UISearchBar text field?

It turns out that the contents of the UISearchBar does not change correctly with the outer layer. Therefore, you need to call -layoutSubviews: inside the animation block after the frame is set in the search bar. Thus, the block ends as:

 [findField setFrame:CGRectMake(findField.bounds.origin.y, findField.bounds.origin.y, findFieldWidth, findField.bounds.size.height)]; [findField layoutSubviews]; [UIView commitAnimations]; 

Reputation for Nick Farina!

+12
source share

I had the same problem when trying to animate the width of a UISearchBar .

In iOS 4 and later, I found that using UIViewAnimationOptionLayoutSubviews as an option for

 +[UIView animateWithDuration:delay:options:animations:completion:] 

fixed it.

+7
source share

The accepted answer works, but according to Apple's docs, you "shouldn't call this method." A clean solution is to use the layoutIfNeeded method:

 [UIView animateWithDuration:UINavigationControllerHideShowBarDuration delay:0.f options:UIViewAnimationOptionCurveEaseInOut animations:^{ [searchBar setFrame: ... [searchBar layoutIfNeeded]; ... 

Enjoy it!

+3
source share

Sorry, this is a bit outdated, but I had a similar problem. I did not want to use layoutSubviews because the documentation says that you should not directly access this method.

What I did to solve my problem was calling sizeToFit in a preview in the animation block.

+1
source share

All Articles