iPhone:默认隐藏UITableViewsearch栏

我使用Interface Builder来创build一个表格视图,我添加了库的search栏和search显示控制器来添加searchfunction。 但是,IB将其设置为当视图第一次显示时,屏幕顶部会显示该条。

我想知道如何让默认情况下隐藏search栏,但仍然可以与表视图(例如苹果的邮件应用程序)滚动。 我已经尝试调用scrollRectToVisible:animated:viewDidLoad向下滚动表视图,但无济于事。 默认情况下隐藏search栏的首选方式是什么?

首先确保将UISearchBar添加到UITableView的tableHeaderView中,以便与表格内容一起滚动,而不是固定在视图顶部。

search栏不会被视为tableview中的一行,所以如果您将tableview的顶部滚动到第一行,它会隐藏search栏:

 [yourTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO]; 

或在Swift中:

 yourTableView.scrollToRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 0), atScrollPosition: UITableViewScrollPosition.Top, animated: false) 

确保在包含数据之前不要滚动tableview(如果给定的indexPath不指向有效的行(即,如果tableview为空), scrollToRowAtIndexPath将引发exception)。

不要添加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)]; } 

我也得到取消button来再次隐藏….(并删除键盘)

 - (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar { [self.tableView setContentOffset:CGPointMake(0, 44) animated:YES]; [self.searchBar resignFirstResponder]; } 

contentOffset在Tim和Joe D'Andrea的评论中被注意到了,但是通过添加一个隐藏search栏的animation来扩展它。 我注意到search栏只是消失了,这有点意外。

对于那些想要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]; 

这个解决scheme有很多答案,但是没有一个对我很好。

这完美的作品。 没有animation,并通过-viewDidLoad完成

  - (void)viewDidLoad { [super viewDidLoad]; self.tableView.contentOffset = CGPointMake(0, self.searchBar.frame.size.height - self.tableView.contentOffset.y); } 

注意:

代码假定你有searchBar链接到search栏。 如果不是,则可以使用self.searchDisplayController.searchBar

我的目标是当视图控制器被加载时隐藏添加到故事板中的简单TableView风格的tableHeaderView的search栏,并且当用户在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() 

以上都没有为我工作,以防万一有人会有同样的问题。

我在searchBar设置为tableHeaderView 。 在viewDidLoad我有tableView.contentOffset = CGPointMake(0, 44); 保持searchBar最初“隐藏”。 当用户向下滚动searchBarsearchBar

目标:隐藏search栏取消button点击

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是后面的工具栏

这工作: tableView.setContentOffset(CGPointMake(0, -20)

似乎不合逻辑,但只有-20移动到正确的位置

内容偏移是要走的路,但它不能100%的工作。

如果将estimatedRowHeight设置为固定estimatedRowHeight ,则不起作用。 我不知道现在的工作。 我已经创build了一个显示问题的项目 ,并且我已经创build了一个苹果的雷达 。

如果你想要一个快速的例子来设置它,请检查这个项目。

对于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) 

请注意,如果在tableview中没有数据,接受的答案将会崩溃。 在某些情况下将其添加到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)]; } 

当没有足够的行填充tableView时,所有现有解决scheme都不适用于iOS 8,因为iOS会在这种情况下自动调整插入。 (当有足够的行时,现有的答案是好的)

在这个问题上浪费了6个小时之后,我终于得到了这个解决scheme。

简而言之,如果没有足够的单元格,则需要将空单元格插入到tableView中,因此tableView的内容大小足够大,iOS将不会为您调整插入点。

下面是我在Swift中做的事情:

1.)声明一个variablesminimumCellNum作为一个类的属性

 var minimumCellNum: Int? 

2.)计算minimumCellNum并在viewWillAppear设置tableView.contentOffset

 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.)在storyboard和tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath)注册一个空单元格,其selection属性为None

 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 } 

这不是一个完美的解决scheme,但它是唯一的解决scheme,真正适用于我在iOS 8上。我想知道是否有一个整洁的解决scheme。

老实说,没有一个答案真的解决了这个问题(对我来说)。 如果你的表视图没有行或行高不同,这些答案是不够的。

唯一的作品:

 - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; self.tableView.contentOffset = (CGPoint){.y = self.tableView.contentOffset.y + self.searchController.searchBar.frame.size.height}; } 

我发现“Notes”应用程序无法在tableView为空时search项目。 所以我认为这只是使用-(void)addSubview:(UIView *)view来首先添加一个空白表。 当你添加一个项目到它的数据源数组时,它会运行另一个代码来加载tableView。

所以我的解决scheme是:

 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内部完成,再加上你不必担心表是否为空(以避免exception)。

 CGRect newBounds = self.tableView.bounds; newBounds.origin.y = newBounds.origin.y + self.searchBar.bounds.size.height; self.tableView.bounds = newBounds; 

一旦用户向下滚动表格,search栏将显示并正常运行

这个问题的其他答案对我来说根本不起作用,在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是否可见(意思是contentOffsety位置,也就是滚动位置,是0 )。 如果是,它只是向下滚动searchBar的高度。 如果searchBar不可见(想象tableView中的项目列表较大),那么它将不会尝试滚动tableView ,因为当您从嵌套行项目返回时,这会弄乱定位。

边注
我build议把这个代码放在一个单独的方法中,以确保单一的责任,并给你重用性,随时在你的代码中调用它。

如果您的表格总是至less有一行,请滚动到表格的第一行,search栏将自动隐藏。

 let firstIndexPath = NSIndexPath(forRow: 0, inSection: 0) 

self.tableView.selectRowAtIndexPath(firstIndexPath,animated:false,scrollPosition:.Top)

如果你把上面的代码放在viewDidLoad中 ,它会抛出一个错误,因为tableView还没有加载,所以你必须把它放在viewDidAppear中,因为这个时候tableView已经加载了。

如果你把它放在viewDidAppear上 ,每次打开tableView就会滚动到顶部。

也许你不希望这种行为,如果tableView保持打开,就像它是一个UITabBar视图控制器或当你做一个继续,然后回来。 如果您只是想在初始加载时滚动到顶部,您可以创build一个variables来检查它是否是初始加载,以便它只滚动一次。

首先在视图控制器类中定义一个名为isInitialLoad的variables,并将其设置为“true”:

 var isInitialLoad = true 

然后检查viewDidAppear上的isInitialLoad是否为true,如果是true,则滚动到顶部并将isInitialLoadvariables设置为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); 

不要忘记考虑状态栏导航栏 。 我的表格视图控制器embedded在导航控制器,在viewDidAppear

 tableView.contentOffset = CGPointMake(0, -20) // -20 = 44 (search bar height) - 20 (status bar height) - 44 (navigation bar height) 

为我工作。

对于Swift:

只是使tableview内容y偏移,这应该像search栏的高度。

 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) } 

我试图设置内容偏移和scrollToIndexpath,但没有令人满意的工作。 我从viewDidLoad中删除tableHeaderView的设置为searchBar,并将其设置在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) } } 

这就像一个魅力。内容偏移设置是为了平滑的滚动目的