This might be a strange question but there might be a different solution for what I'm trying to achieve, I'm open to anything that works as needed!
Facts:
I have a UITableView
with a UISearchBar
handled by a UISearchDisplayController
.
Above said TableView I have some buttons and a small UIScrollView
.
When the user taps the SearchBar and the keyboard comes up, there is very little space to show the search results while typing.
Therefore I want to move the TableView all the way to the top (covering the buttons and the ScrollView) when the user begins a search.
My code and the problem:
- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller {
...
[UIView beginAnimations:@"Search" context:nil];
[UIView setAnimationDuration:0.6];
[self.attractionsTableView setFrame:CGRectMake(0, 0, 320, 400)];
[UIView commitAnimations];
...
return;
}
Now the problem is that since the distance my UITableView
h开发者_Go百科as to travel is about 100 points, the SearchDisplayController is faster with putting the black overlay on top of the TableView and thus the black overlay is already on top while the TableView is still sliding up there.
The result is a screen that looks kinda like this:
problem http://img833.imageshack.us/img833/9186/problemqdu.png
So the user sees the TableView sliding up (which would be fine) but the black overlay is already up there waiting because the searchDisplayController's animation is faster than mine.
So I have a possible idea but don't know how to do this:
Is there a way to set the duration of the animation of the searchDisplayController putting the black overlay on top of the search tableView?
EDIT:
I know I can set the animationDuration to 0.01 or even 0, but the speed of 0.6 seems pretty ok for a distance of 100 points, so I'm trying to find a different solution that lowering the duration.
The trick is not let the run loop run normally until your animation is done. Animations are performed when the run loop is running in a certain mode. Luckily, the overlay animation is performed in a different run loop mode than other animations, which run in the default run loop mode. So, all you have to do is run the run loop from within your method until the animation is complete.
- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller {
BOOL done = NO;
// Pass the done variable's address as the context so we can be notified
[UIView beginAnimations:@"SearchExpand" context:&done];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(animationDone:finished:context:)];
[UIView setAnimationDuration:0.6];
// Expend the table view to fill its superview
self.attractionsTableView.frame = [[self.attractionsTableView superview] bounds];
[UIView commitAnimations];
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
// Run the run loop until the animation completes
while(!done) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
if(![runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]])
break;
[pool drain];
}
}
- (void)animationDone:(NSString *)name finished:(NSNumber *)finished context:(void *)context {
// Set the done flag to YES
*((BOOL*)context) = YES;
// and kill the run loop
CFRunLoopStop(CFRunLoopGetCurrent());
}
精彩评论