Adding a search bar to the top of a UITableView

13,654

Solution 1

Usually you just use UISearchBar as a tableViewHeader for your table view. If you want it hidden when the user enters the screen (like it's done in most native apps) you can just set contentOffset for the tableView in viewWillAppear.
And I am pretty sure that's in fact how they do it. And if you think about it it's what tableHeaderView is meant for.

Try something like this:

- (void)viewDidLoad
{
    [super viewDidLoad];

    UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0., 0., 320., 44.)];
    self.tableView.tableHeaderView = searchBar;
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    CGPoint contentOffset = self.tableView.contentOffset;
    contentOffset.y += CGRectGetHeight(self.tableView.tableHeaderView.frame);
    self.tableView.contentOffset = contentOffset;
}

Note that in iOS 7 you should not just set the contentOffset of your tableView to CGPointMake(0., CGRectGetHeight(self.tableView.tableHeaderView.frame)) if your viewController has automaticallyAdjustsScrollViewInsets set to YES, since it probably will not be CGPointZero in viewWillAppear:

Solution 2

@dariaa's answer updated for Swift 3:

override func viewDidLoad() {
    super.viewDidLoad()
    let searchBar = UISearchBar(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 44))
    self.tableView.tableHeaderView = searchBar
}
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    var contentOffset: CGPoint = self.tableView.contentOffset
    contentOffset.y += (self.tableView.tableHeaderView?.frame)!.height
    self.tableView.contentOffset = contentOffset
}

Though you'll probably need to set the searchBar as a property if you want to use it.

Solution 3

If you only want your search to be visible when the UITableView is scrolled all the way to the top, make a UITableViewCell subclass that houses your UISearchBar. Then, in tableView:cellForRowAtIndexPath, check if the indexPath is (0,0). This is the table view telling you it is creating the cell at the very top, so then just create your search bar cell instead of your default cell.

Code would look something like this:

- (void)viewDidLoad
{
     [self.tableView registerClass:[SearchBarCell class] forCellReuseIdentifier:@"SearchBarCell"];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.row == 0 && indexPath.section == 0) {
        //this is the cell that displays the UISearchBar
        SearchBarCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SearchBarCell"];
        return cell;
    }
    else {
        //create your usual table view cell normally
    }
}

There may be a cleaner way to determine the row and section of the indexPath, but I'm writing this code off the top of my head and don't recall a better way.

Share:
13,654

Related videos on Youtube

wstr
Author by

wstr

Updated on September 15, 2022

Comments

  • wstr
    wstr over 1 year

    I have a UITableView and am currently working on adding a custom search bar at the top consisting of a UIView with a UITextField inside of it. As is standard for iOS apps, the search bar should only be visible when the table view is scrolled to the top — when scrolling down it should disappear off the screen along with the other cells.

    However, I cannot figure out a way to achieve this effect. If I place the search bar at the top of the table view, it will overlay the cell beneath it. If I place it 50 pixels above the table view, it is not possible for the user to select it since it will automatically disappear when the user releases their finger from the screen.

    Can someone please enlighten me as to how to achieve this effect?

  • Stéphane de Luca
    Stéphane de Luca almost 9 years
    Nice, but how would you trigger the hiding once there is nothing in the search bar @dariaa ?
  • Frederic Adda
    Frederic Adda over 8 years
    The searchBar should not be displayed in a cell, but in the tableView header.