2009-07-04 76 views
79

我使用Interface Builder创建了一个表格视图,我添加了库的搜索栏和搜索显示控制器来添加搜索功能。但是,IB将其设置为在视图第一次显示时可以在屏幕顶部显示条。iPhone:默认隐藏UITableView搜索栏

我想知道如何让默认情况下隐藏搜索栏,但仍然可以使用表格视图进行滚动(例如,请参阅Apple's Mail应用程序)。我试过在viewDidLoad中调用scrollRectToVisible:animated:来向下滚动表格视图,但无济于事。默认情况下隐藏搜索栏的首选方式是什么?

回答

110

首先确保将UISearchBar添加到UITableView的tableHeaderView,以便它与表的内容一起滚动并且不固定到视图的顶部。

搜索栏不计为在tableview中的行,因此,如果滚动的tableview的顶部的第一行中,“隐藏”了搜索栏:

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

或夫特:

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

确保不滚动tableview中包含的数据之前(scrollToRowAtIndexPath将引发异常,如果给定indexPath没有指向一个有效行(即如果实现代码如下为空))。

+0

此作品 - 谢谢! – Tim 2009-07-06 23:45:33

+11

其实,我得到的问题是,如果没有足够的行来填充屏幕,表格视图将不会滚动 - 在一行或两行表格中,此代码不会执行任何操作。那是预期的行为?我能以某种方式避开它吗? – Tim 2009-07-10 19:54:22

+0

这样的声音通常是有意的(如果适合屏幕显示所有内容)。然而邮件应用程序似乎可以滚动搜索栏,即使没有行存在。不幸的是,我无法在我自己的代码中重现这一点。 – Zargony 2009-07-14 21:51:21

1

我发现当Notes视图空白时,“Notes”应用程序无法搜索项目。所以我认为这只是使用-(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]; 
} 

希望这有助于:-)

25

的contentOffset由蒂姆和Joe D'安德烈的评论所指出的,但是这是一个有点通过添加扩展动画来隐藏搜索栏。我注意到搜索栏刚刚消失有点意外。

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

44

不要”添加的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]; 
} 
1

更改的tableView的界限,这可以在里面viewDidLoad做,再加上你不必担心,如果表是空的或不是(避免除外)。

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

一旦用户向下滚动搜索栏将出现并表现表正常

7

有很多的答案,这样的解决方案,但是,没有工作对我非常好。

这个效果很好。没有动画,并在-viewDidLoad

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

注:

代码假定你有searchBar@property链接到搜索栏。 如果不是,您可以使用self.searchDisplayController.searchBar而不是

3

请注意,如果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)]; 
} 
4

以上都不为我工作,所以为了以防万一,如果有人将有同样的问题。我有searchBar设置为tableHeaderView在iOS7上的分组表格。在viewDidLoad我有tableView.contentOffset = CGPointMake(0, 44);保持searchBar最初“隐藏”。当用户向下滚动searchBar是dsiplayed

目标:隐藏取消按钮自来水

搜索栏在searchBarCancelButtonClicked(searchBar: UISearchBar!)

这不起作用:[yourTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];的tableView被滚动太多了,导致零行在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移动它到正确的位置

2

老实说,没有任何答案真的解决了这个问题(对我来说)。如果你的表视图没有行或行高不同,这些答案是不够的。加入的故事板平原TableView中的风格tableHeaderView

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

我的目标是隐藏搜索栏时,视图控制器被加载并显示栏时,在顶部用户向下滚动:

唯一可行的事的UITableView。 所以,我使用斯威夫特并增加了扩展:

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() 
1

其他回答这个问题无论是在没有工作所有对我来说,在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,因为当您从嵌套的订单项返回时,这会弄乱定位。

旁注
我建议把这个代码在一个单独的方法来确保单一职责,并给您的可重用性在代码中随时调用它。

4

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

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

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

下面是我在Swift中做的:

1。)声明变量minimumCellNum作为一类属性

var minimumCellNum: Int? 

2.)计算minimumCellNumviewWillAppear

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.设置tableView.contentOffset)注册一个空格,其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 
} 

tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)

if tableView == self.tableView { 
    if numOfYourRows < (indexPath.row + 1) { 
     return 
    } 
    YOUR LOGIC OF SELECTING A CELL 
} 

这不是一个完美的解决方案,但它是唯一的解决方法是真的对我的作品在iOS 8.我想知道如果有5)一个整洁的解决方案。

1

如果您的表格总是至少有一行,只需滚动到表格的第一行,搜索栏就会自动隐藏起来。

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

self.tableView.selectRowAtIndexPath(firstIndexPath,动画:假的,则scrollPosition:.TOP)

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

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

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

第一定义一个称为isInitialLoad变量在视图控制器类和它设置为等于“真”:

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

内容偏移量是要走的路,但它不能100%运行。

如果将estimatedRowHeight设置为固定值,则不起作用。我还不知道这方面的工作。我创建了一个project显示了这个问题,我创建了一个与苹果公司的radar

如果你想要一个快速设置的例子,请查看该项目。

0

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

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

为我工作。

0

对于斯威夫特:

只是要实现代码如下内容y偏移,这应该是像搜索栏的高度。

self.tableView.contentOffset = CGPointMake(0, self.searchController.searchBar.frame.size.height) 
5

对于斯威夫特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) 
0

斯威夫特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) 
} 
1

下面的代码为我工作

self.tableView.contentOffset = CGPointMake(0.0, 44.0); 
0

我尝试设置内容偏移和scrollToIndexpath但没有满意的工作。我删除tableHeaderView的设置从viewDidLoad中搜索栏,并设置滚动型代表如下

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

这工作就像一个charm.The内容偏移设置为平滑滚动目的

0

我有类似的问题。唯一的办法,我发现解决这个问题是在UITableView contentOffset属性上使用键值观察者。

经过一些调试,我发现问题出现只是如果表视图的内容大小比tableview小。我在viewWillAppear时开始KVO。 并且出现查看后0.3秒的发送停止KVO。每当contentOffset变为0.0时,KVO会在搜索栏高度上反应并设置contentOffset。 我在0.3秒后停止KVO异步,因为即使在视图出现之后,视图布局也会重置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"]; 
}