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
最初“隐藏”。 当用户向下滚动searchBar
被searchBar
目标:隐藏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是否可见(意思是contentOffset
的y
位置,也就是滚动位置,是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) } }
这就像一个魅力。内容偏移设置是为了平滑的滚动目的