Я использовал Interface Builder для создания табличного представления, к которому я добавил панель поиска библиотеки и контроллер отображения поиска, чтобы добавить функции поиска. Однако IB настроил его таким образом, чтобы полоса была видна вверху экрана при первом отображении представления.
Я хотел бы знать, как сделать так, чтобы панель поиска была скрыта по умолчанию, но по-прежнему прокручивалась в виде таблицы (см. Пример в приложении Apple Mail). Я пытался дозвониться scrollRectToVisible:animated:
в viewDidLoad
прокрутить вид таблицы вниз, но безрезультатно. Какой предпочтительный способ скрыть панель поиска по умолчанию?
contentOffset
с любым значением будет нарушена, если вы используете сложную компоновку контроллера представления. Не рекомендую.Не добавляйте UISearchBar как часть UITableView, в этом нет необходимости.
UITableView имеет свойство tableHeaderView, которое идеально подходит для этого:
- (void) viewDidLoad { [super viewDidLoad]; self.searchBar = [[[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)] autorelease]; self.searchBar.showsCancelButton = YES; self.searchBar.delegate = self; self.tableView.tableHeaderView = self.searchBar; }
Если вы не хотите видеть его по умолчанию:
- (void) viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [self.tableView setContentOffset:CGPointMake(0, 44)]; }
Я также получаю кнопку отмены, чтобы снова ее скрыть .... (и убрать клавиатуру)
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar { [self.tableView setContentOffset:CGPointMake(0, 44) animated:YES]; [self.searchBar resignFirstResponder]; }
источник
viewWillAppear
- плохая идея, потому что он будет запускаться каждый раз, когда вы вернетесь к своему представлению. Это означает, что ваш tableview будет медленно уменьшаться. Раздражающий баг!ContentOffset был отмечен в комментариях Тима и Джо Д'Андреа, но его немного расширили за счет добавления анимации, скрывающей панель поиска. Я заметил, что это немного неожиданно, когда панель поиска просто исчезает.
Небольшое обновление для тех, кто хочет ориентироваться на iOS 4.0 и выше, попробуйте следующее:
[UIView animateWithDuration:0.4 animations:^{ self.tableView.contentOffset = CGPointMake(0, self.searchDisplayController.searchBar.frame.size.height); } completion:nil];
Предыдущий ответ:
[UIView beginAnimations:@"hidesearchbar" context:nil]; [UIView setAnimationDuration:0.4]; [UIView setAnimationBeginsFromCurrentState:YES]; self.tableView.contentOffset = CGPointMake(0, self.searchDisplayController.searchBar.frame.size.height); [UIView commitAnimations];
источник
viewDidAppear:
вместоviewDidLoad
.На это решение есть много ответов, но ни один из них не сработал для меня.
Это прекрасно работает. Без анимации и делается на
-viewDidLoad
- (void)viewDidLoad { [super viewDidLoad]; self.tableView.contentOffset = CGPointMake(0, self.searchBar.frame.size.height - self.tableView.contentOffset.y); }
Заметка:
Код предполагает, что у вас есть
searchBar
@property
ссылка на панель поиска. Если нет, вы можете использоватьself.searchDisplayController.searchBar
вместо этогоисточник
-viewWillAppear
не работает ... Вызывается ли он, когда контроллер вкладки переключается на представление?Для Swift 3+
Я сделал это:
Объявите это
var
:var searchController = UISearchController()
И в
viewDidLoad()
методеsearchController = UISearchController(searchResultsController: nil) searchController.searchResultsUpdater = self searchController.hidesNavigationBarDuringPresentation = false searchController.dimsBackgroundDuringPresentation = true searchController.searchBar.placeholder = NSLocalizedString("Search", comment: "") definesPresentationContext = true tableView.tableHeaderView = searchController.searchBar tableView.contentOffset = CGPoint(x: 0, y: searchController.searchBar.frame.size.height)
источник
Моя цель состояла в том, чтобы скрыть панель поиска, добавленную в tableHeaderView простого стиля TableView в раскадровке, когда загружается контроллер представления, и отображать панель, когда пользователь прокручивает вниз в верхней части UITableView. Итак, я использую Swift и добавил расширение:
extension UITableView { func hideSearchBar() { if let bar = self.tableHeaderView as? UISearchBar { let height = CGRectGetHeight(bar.frame) let offset = self.contentOffset.y if offset < height { self.contentOffset = CGPointMake(0, height) } } } }
в viewDidLoad () просто вызовите:
self.tableView.hideSearchBar()
источник
Все существующие решения не работают для меня на iOS 8, когда недостаточно строк для заполнения tableView, поскольку iOS в этой ситуации автоматически настроит вставку. (Существующие ответы хороши, если строк достаточно)
Потратив около 6 часов на эту проблему, я наконец получил это решение.
Короче говоря, вам нужно вставить пустые ячейки в tableView, если ячеек недостаточно, поэтому размер содержимого tableView достаточно велик, и iOS не будет настраивать вставку для вас.
Вот как я это сделал в Swift:
1.) объявить переменную
minimumCellNum
как свойство классаvar minimumCellNum: Int?
2.) рассчитать
minimumCellNum
и установитьtableView.contentOffset
вviewWillAppear
let screenHeight = Int(UIScreen.mainScreen().bounds.height) // 101 = Height of Status Bar(20) + Height of Navigation Bar(44) + Height of Tab Bar(49) // you may need to subtract the height of other custom views from the screenHeight. For example, the height of your section headers. self.minimumCellNum = (screenHeight - 103 - heightOfOtherCustomView) / heightOfYourCell self.tableView.contentOffset = CGPointMake(0, 44)
3.) в
tableView(tableView: UITableView, numberOfRowsInSection section: Int))
let numOfYourRows = YOUR LOGIC if numOfYourRows > minimumCellNum { return numOfYourRows } else { return minimumCellNum! }
4.) Зарегистрируйте пустую ячейку с
selection
атрибутомNone
в раскадровке и вtableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath)
if indexPath.row < numOfYourRows { return YOUR CUSTOM CELL } else { let cell = tableView.dequeueReusableCellWithIdentifier("EmptyCell", forIndexPath: indexPath) as! UITableViewCell return cell }
5.) в
tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
if tableView == self.tableView { if numOfYourRows < (indexPath.row + 1) { return } YOUR LOGIC OF SELECTING A CELL }
Это не идеальное решение, но это единственный обходной путь, который действительно работает для меня на iOS 8. Я хотел бы знать, есть ли более изящное решение.
источник
Ничего из вышеперечисленного не помогло мне, так что на всякий случай, если у кого-то будет такая же проблема.
Я
searchBar
установил какtableHeaderView
на сгруппированной таблице на iOS7. ВviewDidLoad
я должен изначальноtableView.contentOffset = CGPointMake(0, 44);
сохранитьsearchBar
"скрытым". Когда пользователь прокручивает внизsearchBar
, отображаетсяЦель: скрыть панель поиска при нажатии кнопки отмены
В
searchBarCancelButtonClicked(searchBar: UISearchBar!)
Это не сработало:
[yourTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];
tableView слишком сильно прокручивался вверх, в результате чего строка 0 находилась за toolBar.Не сработало:
tableView.ContentOffset = CGPointMake(0, 44)
- ничего не происходитНе сработало:
tableView.ContentOffset = CGPointMake(0, searchBar.frame.size.height)
- ничего не происходитЭто не сработало:
tableView.setContentOffset(CGPointMake(0, 44), animated: true);
снова tableView слишком сильно прокручивался вверх, в результате чего строка 0 находилась за toolBar.Это сработало частично:
tableView.setContentOffset(CGPointMake(0, 0)
ноtitleForHeaderInSection
было за toolBarЭТО РАБОТАЕТ:
tableView.setContentOffset(CGPointMake(0, -20)
Вроде не логично, но только -20 переместил его в правильное положение
источник
CGRectGetHeight(searchBar.bounds)
?ContentOffset
решений не будет работатьСмещение содержимого - это способ пойти, но он не работает в 100% случаев.
Это не работает, если установлено
estimatedRowHeight
фиксированное число. Я пока не знаю, как обойтись. Я создал проект, показывающий проблему (ы), и я создал радар с Apple.Ознакомьтесь с проектом, если вам нужен быстрый пример того, как все это настроить.
источник
Обратите внимание, что принятый ответ выйдет из строя, если в табличном представлении нет данных. И добавление его в viewDidLoad может не работать при определенных обстоятельствах.
[yourTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO]; // crashes if no rows/data
Поэтому вместо этого добавьте эту строку кода:
- (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; [yourTableView setContentOffset:CGPointMake(0, self.searchDisplayController.searchBar.frame.size.height)]; }
источник
Честно говоря, ни один из ответов не решил проблему (для меня). Если в вашем табличном представлении нет строк ИЛИ высота строк отличается, этих ответов недостаточно.
Единственное, что работает:
- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; self.tableView.contentOffset = (CGPoint){.y = self.tableView.contentOffset.y + self.searchController.searchBar.frame.size.height}; }
источник
self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
.В
scrollToRowAtIndexPath
Метод вызывает сбой , если есть нулевые строки в таблице.UITableView - это просто просмотр с прокруткой, поэтому вы можете просто изменить смещение содержимого.
Это проверяет, что у вас есть что-то в качестве tableHeaderView, и предполагая, что вы выполняете прокрутку, чтобы скрыть это
if let searchHeight = tableView.tableHeaderView?.frame.height { tableView.setContentOffset(CGPoint.init(x: 0, y:searchHeight ), animated: false) }
источник
Я обнаружил, что приложение «Заметки» не может искать элементы, когда tableView пуст. Поэтому я думаю, что
-(void)addSubview:(UIView *)view
сначала нужно просто добавить пустую таблицу. Когда вы добавляете элемент в его массив источника данных, он запускает еще один фрагмент кода для загрузки tableView.Итак, мое решение:
if([self.arrayList count] > 0) { [self.tableView reloadData]; //use jdandrea's code to scroll view when cell==nil in cellForRowAtIndexPath self.tableView.scrollEnabled = YES; } else { tableBlank = [[UITableView alloc]initWithFrame:CGRectMake(0,0,320,416) style:UITableViewStylePlain] autorelease]; tableBlank.delegate = self; tableBlank.dataSource = self; [self.view addSubview:tableBlank]; }
Надеюсь это поможет :-)
источник
Измените границы tableView, это можно сделать внутри,
viewDidLoad
и вам не нужно беспокоиться о том, пуста таблица или нет (чтобы избежать исключения).CGRect newBounds = self.tableView.bounds; newBounds.origin.y = newBounds.origin.y + self.searchBar.bounds.size.height; self.tableView.bounds = newBounds;
Как только пользователь прокрутит таблицу вниз, появится панель поиска, которая будет вести себя нормально.
источник
Другие ответы на этот вопрос либо вообще не работали для меня, либо имели странное поведение, когда в tableView было 0 строк, либо меняли положение прокрутки при переходе между родительскими и вложенными элементами строки. Это сработало для меня (цель - скрыть UISearchBar при загрузке):
public override func viewWillAppear(animated: Bool) { if self.tableView.contentOffset.y == 0 { self.tableView.contentOffset = CGPoint(x: 0.0, y: self.searchBar.frame.size.height) } }
Пояснение В
любое время,
tableView
когда появится, этот код проверяет, виден ли UISearchBar (что означает, чтоy
позицияcontentOffset
, также известная как позиция прокрутки, есть0
). Если да, то просто прокручивается вниз по высоте searchBar. Если searchBar не виден (подумайте о большем списке элементовtableView
), он не будет пытаться прокрутитьtableView
, так как это испортит позиционирование, когда вы вернетесь из вложенной строки.Боковое примечание
Я бы рекомендовал поместить этот код в отдельный метод, чтобы обеспечить единоличную ответственность и дать вам возможность многократно вызывать его в любое время в вашем коде.
источник
Если в вашей таблице всегда будет хотя бы одна строка, просто прокрутите до первой строки таблицы, и панель поиска будет автоматически скрыта.
let firstIndexPath = NSIndexPath(forRow: 0, inSection: 0)
self.tableView.selectRowAtIndexPath (firstIndexPath, анимированный: false, scrollPosition: .Top)
Если вы поместите приведенный выше код в viewDidLoad , он выдаст ошибку, потому что tableView еще не загружен, поэтому вам нужно поместить его в viewDidAppear, потому что к этому моменту tableView уже загружен.
Если вы поместите его в viewDidAppear , каждый раз, когда вы открываете tableView, он будет прокручиваться вверх.
Возможно, вам не нужно такое поведение, если tableView остается открытым, например, когда это UITabBar View Controller или когда вы выполняете переход, а затем возвращаетесь. Если вы просто хотите, чтобы он прокручивался вверх при начальной загрузке, вы можете создать переменную, чтобы проверить, является ли это начальной загрузкой, чтобы она прокручивалась вверх только один раз.
Сначала определите переменную с именем isInitialLoad в классе контроллера представления и установите для нее значение «true»:
var isInitialLoad = true
Затем проверьте, истинно ли isInitialLoad для viewDidAppear, и, если это правда, прокрутите вверх и установите для переменной isInitialLoad значение false:
if isInitialLoad { let firstIndexPath = NSIndexPath(forRow: 0, inSection: 0) self.tableView.selectRowAtIndexPath(firstIndexPath, animated: false, scrollPosition: .Top) isInitialLoad = false }
источник
Ниже код работает для меня
self.tableView.contentOffset = CGPointMake(0.0, 44.0);
источник
Я попытался установить смещение содержимого и scrollToIndexpath, но ничего не получилось. Я удалил настройку tableHeaderView как searchBar из viewDidLoad и установил ее в делегате scrollview, как показано ниже
override func scrollViewWillBeginDragging(scrollView: UIScrollView) { if scrollView.contentOffset.y < 0 && tableView.tableHeaderView == nil { tableView.tableHeaderView = searchController.searchBar tableView.setContentOffset(CGPointMake(0, scrollView.contentOffset.y + searchController.searchBar.frame.size.height), animated: false) } }
Это сработало как шарм. Настройка смещения содержимого предназначена для плавной прокрутки.
источник
Не забудьте взять с собой строку состояния и панель навигации во внимание. Мой контроллер табличного представления встроен в контроллер навигации, в
viewDidAppear
:tableView.contentOffset = CGPointMake(0, -20) // -20 = 44 (search bar height) - 20 (status bar height) - 44 (navigation bar height)
работал у меня.
источник
Для Swift:
Просто сделайте смещение содержимого таблицы по оси y, которое должно быть похоже на высоту панели поиска.
self.tableView.contentOffset = CGPointMake(0, self.searchController.searchBar.frame.size.height)
источник
Swift 3
работает и с пустой таблицей!
В своей среде я загружаю пользовательские ячейки с помощью файла xib, и rowHeight устанавливается автоматически.
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { self.tableView.contentOffset = CGPoint(x: 0, y: self.tableView.contentOffset.y + self.searchController.searchBar.bounds.height) }
источник
У меня была аналогичная проблема. И единственный способ решить эту проблему, который я нашел, заключался в использовании наблюдателя ключевого значения в свойстве UITableView contentOffset.
После некоторой отладки я понял, что проблема возникает, только если размер содержимого табличного представления меньше, чем табличное представление. Я запускаю КВО, когда на viewWillAppear. И отправка остановится KVO через 0,3 секунды после появления просмотра. Каждый раз, когда contentOffset становится равным 0,0, KVO реагирует и устанавливает contentOffset на высоту панели поиска. Я останавливаю асинхронный KVO через 0,3 секунды, потому что макет представления сбрасывает contentOffset даже после появления представления.
- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [self.tableView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil]; } -(void)viewDidAppear:(BOOL)animated{ __weak typeof (self) weakSelf = self; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [weakSelf.tableView removeObserver:self forKeyPath:@"contentOffset"];}); } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{ if ([keyPath isEqualToString:@"contentOffset"] && self.tableView.contentOffset.y == 0.0) { self.tableView.contentOffset = CGPointMake(0, CGRectGetHeight(self.tableView.tableHeaderView.frame)); } } -(void)dealloc { [self.tableView removeObserver:self forKeyPath:@"contentOffset"]; }
источник