UISearchController search bar overlap first cell when active

给你一囗甜甜゛ 提交于 2020-01-20 08:44:25

问题


I am using UISearchController to search for data in my tableview. I am not using table view controller. I would like to hide the navigation bar when my search bar is active therefore I set self.searchController.hidesNavigationBarDuringPresentation = YES; to yes.

However when I do this and want to search, my active search bar covers part of the first cell. the covered part has same height as status bar.

I tried other articles and questions similar to this one but nothing helped me to solve it. Then I started to play with the table view header size. I did this

 -(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{

  return 20.0f;
}

The result was that when I tapped search bar an started to search problem was not there anymore.

However when the search bar is not active there was a gab between searchbar and first cell

Any ideas how to fix this issue?

Edit: after adding self.automaticallyAdjustsScrollViewInsets = false;


回答1:


This is how I set up the search bar and things in viewDidLoad (copied from some of apple's examples).

It presents the found results in the same view controller as your unfiltered data is shown. It also has its search bar in the table header that is hidden until it is needed.

self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
self.searchController.searchResultsUpdater = self;
self.tableView.tableHeaderView = self.searchController.searchBar;
[self.searchController.searchBar sizeToFit];

// we want to be the delegate for our filtered table so didSelectRowAtIndexPath is called for both tables
self.searchController.delegate = self;
self.searchController.dimsBackgroundDuringPresentation = NO; // default is YES
self.searchController.searchBar.delegate = self; // so we can monitor text changes + others

// Search is now just presenting a view controller. As such, the normal view controller
// presentation semantics apply. Namely, that presentation will walk up the view controller
// hierarchy until it finds the root view controller or one that defines a presentation context.
//
self.definesPresentationContext = YES;  // know where you want UISearchController to be displayed

// Hides search bar initially. When the user pulls down on the list, the search bar is revealed.
[self.tableView setContentOffset:CGPointMake(0, self.searchController.searchBar.frame.size.height)];



回答2:


I managed to resolve this issue by combining RJiryes answer with scroll to top.

-(void)willPresentSearchController:(UISearchController *)searchController{

     [self.contactsTableView setContentInset:UIEdgeInsetsMake(20, 0, 0, 0)];
     [self.contactsTableView setContentOffset:CGPointMake(0.0f, -self.contactsTableView.contentInset.top) animated:YES];
 }

-(void)willDismissSearchController:(UISearchController *)searchController{

     [self.contactsTableView setContentInset:UIEdgeInsetsMake(0, 0, 0, 0)];
}



回答3:


You can add content inset from the top instead of adding a header.

  self.tableView.contentInset = UIEdgeInsets(top: 20, left: 0, bottom: 0, right: 0)

and when willDismissSearchController (UISearchController's delegate method) is called, return the insets to 0

  self.tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)

This way, you'll avoid the whitespace when it's not active.




回答4:


Not the best solution but just to workaround.

-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { return searchController.isActive ? 20.0f : 0.0f; }




回答5:


I have seen similar behavior. Most probably, your table view controller is not implementing heightForHeaderInSection. Precise height of cell is not known, this leads to number of issues like yours.




回答6:


Reseting tableView.tableHeaderView = searchController.searchBar after the dismissing searchController solved the issue for me.

  public func didDismissSearchController(_ searchController: UISearchController) {
            tableView.tableHeaderView = searchController.searchBar
}

Unfortunately didDismissSearchController doesn't get called if you select a result and go back to parent viewController. In this case you need reset the searchBar.frame back to origin position:

if let frame = tableView.tableHeaderView?.frame {
    searchController.searchBar.frame = frame
}



回答7:


I got the same issue and fixed it by adding the following method under viewWillAppear, so it adjusts every time you present that view.

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    setupSearchBar()
}

private func setupSearchBar() {
    definesPresentationContext = true

    let searchController = UISearchController(searchResultsController: nil)

    navigationItem.hidesSearchBarWhenScrolling = false
    searchController.searchBar.placeholder = Constants.searchPlaceholderText
    searchController.searchBar.delegate = self
    searchController.delegate = self

    searchController.obscuresBackgroundDuringPresentation = false
    definesPresentationContext = true

    searchController.searchBar.returnKeyType = .done
    navigationItem.searchController = searchController

    self.navigationItem.hidesSearchBarWhenScrolling = false

}



回答8:


I have the same trouble. And research didn't answer. My decision:

1) I used UITableviewController with SearchController and when I taped on the field I had this UI trouble: Extra blank space between searchBar and tableview The guys noted that you need to use the searchController with UIViewcontroller and tableView separately. So I did

2) There was this problem. It is solved as follows:

 let searchController = UISearchController(searchResultsController: nil)
var tableView:UITableView!

override func viewDidLoad() {
    super.viewDidLoad()

    loadData()
    setupTableView()
    setupSearchController()
}

private func setupTableView(){

    tableView = UITableView(frame: CGRect.zero, style: .plain)

    **//next 2 very important line of code**

    tableView.autoresizingMask = UIViewAutoresizing()
    tableView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(tableView)

    tableView.dataSource = self
    tableView.delegate = self
    tableView.register(LetterBrandCell.self, forCellReuseIdentifier: "brandCell")
    tableView.tableFooterView = UIView()
    addConstraints()
}

In the method of adding constraints, it is important to be attached to top & bottomLayoutGuides, not just to view:

private func addConstraints(){

    NSLayoutConstraint(item: tableView,
                       attribute: .top,
                       relatedBy: .equal,
                       toItem: topLayoutGuide,
                       attribute: .bottom,
                       multiplier: 1,
                       constant: 0).isActive = true

    NSLayoutConstraint(item: tableView,
                       attribute: .bottom,
                       relatedBy: .equal,
                       toItem: bottomLayoutGuide,
                       attribute: .top,
                       multiplier: 1,
                       constant: 0).isActive = true
    NSLayoutConstraint(item: view,
                       attribute: .leading,
                       relatedBy: .equal,
                       toItem: tableView,
                       attribute: .leading,
                       multiplier: 1,
                       constant: 0).isActive = true
    NSLayoutConstraint(item: view,
                       attribute: .trailing,
                       relatedBy: .equal,
                       toItem: tableView,
                       attribute: .trailing,
                       multiplier: 1,
                       constant: 0).isActive = true

}


来源:https://stackoverflow.com/questions/44929810/uisearchcontroller-search-bar-overlap-first-cell-when-active

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!