#ios #uitableview #animation #uisearchdisplaycontroller
#iOS #uitableview #Анимация #uisearchdisplaycontroller
Вопрос:
Это может быть странный вопрос, но может быть другое решение для того, чего я пытаюсь достичь, я открыт для всего, что работает по мере необходимости!
Факты:
У меня есть a UITableView
с a UISearchBar
, обрабатываемый a UISearchDisplayController
.
Выше указанного TableView у меня есть несколько кнопок и маленький UIScrollView
.
Когда пользователь нажимает на панель поиска и появляется клавиатура, для отображения результатов поиска во время ввода остается очень мало места.
Поэтому я хочу переместить TableView полностью наверх (закрыв кнопки и ScrollView), когда пользователь начинает поиск.
Мой код и проблема:
- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller {
...
[UIView beginAnimations:@"Search" context:nil];
[UIView setAnimationDuration:0.6];
[self.attractionsTableView setFrame:CGRectMake(0, 0, 320, 400)];
[UIView commitAnimations];
...
return;
}
Теперь проблема в том, что, поскольку расстояние, которое я UITableView
должен пройти, составляет около 100 точек, searchDisplayController работает быстрее, помещая черное наложение поверх TableView, и, таким образом, черное наложение уже находится сверху, в то время как TableView все еще скользит туда.
В результате получается экран, который выглядит примерно так:
проблема http://img833.imageshack.us/img833/9186/problemqdu.png
Таким образом, пользователь видит, что TableView скользит вверх (что было бы хорошо), но черное наложение уже там, потому что анимация searchDisplayController быстрее, чем у меня.
Итак, у меня есть возможная идея, но я не знаю, как это сделать:
Есть ли способ установить продолжительность анимации searchDisplayController, поместив черное наложение поверх таблицы поиска?
Редактировать:
Я знаю, что могу установить для animationDuration значение 0.01 или даже 0, но скорость 0.6 кажется вполне приемлемой для расстояния в 100 точек, поэтому я пытаюсь найти другое решение, которое уменьшает продолжительность.
Ответ №1:
Хитрость заключается в том, чтобы не позволять циклу выполнения работать нормально, пока ваша анимация не будет выполнена. Анимации выполняются, когда цикл выполнения выполняется в определенном режиме. К счастью, анимация наложения выполняется в другом режиме цикла выполнения, чем другие анимации, которые выполняются в режиме цикла выполнения по умолчанию. Итак, все, что вам нужно сделать, это запустить цикл выполнения из вашего метода, пока анимация не будет завершена.
- (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:amp;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());
}
Комментарии:
1. работает как шарм! удивительно! 🙂 ты мужик! Однако один вопрос: для чего используется аргумент (NSNumber *)finished в методе (void)animationDone?
2. Еще один вопрос: есть ли какая-либо документация по этому поводу? Потому что я вроде бы понял это, но я не думаю, что мог бы использовать это в каком-либо другом контексте. И есть ли способ узнать, выполняется ли анимация в этом «другом режиме цикла выполнения»?
3. Третий вопрос (извините).. Я не понимаю, почему мы создаем новый NSAutoreleasePool в цикле while. Я просто попытался прокомментировать это, чтобы, возможно, найти исключение, которое помогло бы мне понять, для чего оно, но оно все еще работает без пула. Это плохой код или я создал утечку памяти или что-то в этом роде?
4. @Octoshape
finished
Аргумент будет содержатьYES
, завершена ли анимация иNO
была ли она остановлена. Анимация, выполняемая в другом режиме, не документирована. Я узнал методом проб и ошибок. Пул авторелиза — это, по сути, мера безопасности, поскольку вы не знаете, что произойдет в цикле выполнения. Может быть сгенерирован значительный объем автоматически освобождаемой памяти.5. Это абсолютно ЛУЧШЕЕ решение, которое я когда-либо видел для решения проблемы с пользовательским интерфейсом! 🙂 Слава за «наплевать». 🙂