简体   繁体   中英

Floating/fixed search bar above TableView - Swift 3

I'm having a problem that many other users have asked about on StackOverflow (examples: 1 , 2 , 3 ).

I'd like to have a fixed search bar when scrolling a tableview. I originally had a UITableViewController with a UISearchBar on top.

Most solutions recommended that I should have a UIViewController with a UISearchBar and a UITableView below it. I did exactly this. Below is a screenshot of my interface builder.

IB

This solution doesn't fix it, however :( The search bar still doesn't float, and when scrolling it will hide behind the navigation bar.

I have also tried this solution but I'd rather not have the search bar in the navigation bar itself.

Here's all of my TableView or Search related code (I removed everything irrelevant):

class NumberSelectorViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate, UISearchControllerDelegate {

    @IBOutlet var searchBar: UISearchBar!
    @IBOutlet var tableView: UITableView!

    let searchController = UISearchController(searchResultsController: nil)

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.delegate = self
        tableView.dataSource = self

        searchController.searchResultsUpdater = self as UISearchResultsUpdating
        searchController.dimsBackgroundDuringPresentation = false
        definesPresentationContext = true

        // NOTE: Removing thie line removes the search bar entirely.
        tableView.tableHeaderView = searchController.searchBar

        addCancelButton()

    }

    // MARK: - Table view data source

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if isSearching() == true {
            return filteredNumberList.count
        }
        return NumberList.count
    }


    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "numberCell")! as UITableViewCell

        if isSearching() == true {
            cell.textLabel?.text = filteredNumberList[indexPath.row].NumberName
        } else {
            cell.textLabel?.text = NumberList[indexPath.row].NumberName
        }
        return cell
    }

    // MARK: - Table view delegate

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        if isSearching() == true {
            selectedNumber = filteredNumberList[indexPath.row]
        } else {
            selectedNumber = NumberList[indexPath.row]
        }
        performSegue(withIdentifier: "someSegue", sender: self)
    }

    // MARK: Searching

    func filterContentForSearchText(searchText: String, scope: String = "All") {
        filteredNumberList = NumberList.filter({ (Number) -> Bool in
            return (Number.NumberName?.lowercased().contains(searchText.lowercased()))!
        })

        tableView.reloadData()
    }

    // MARK: Search Bar

    func isSearching() -> Bool {
        return (searchController.isActive && searchController.searchBar.text != "")
    }

    func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
    }

    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        filteredNumbersList.removeAll()
    }

    func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
        self.tableView.reloadData()
    }

    extension NumberSelectorViewController: UISearchResultsUpdating {
        public func updateSearchResults(for searchController: UISearchController) {
            filterContentForSearchText(searchText: searchController.searchBar.text!)
        }

        func updateSearchResultsForSearchController(searchController: UISearchController) {
            filterContentForSearchText(searchText: searchController.searchBar.text!)
        }
    }
}

I actually discovered the answer. The issue was simply that I had the line:

tableView.tableHeaderView = searchController.searchBar

I removed this, and then the search bar disappeared, but it was only being hidden behind the navigation bar! So I played around with the constraints on the interface builder and it now works as normal :)

It appears you added the search bar to your view properly, it's just hidden under navigation bar. Try in viewDidLoad

self.edgesForExtendedLayout = UIRectEdgeNone;  

and get rid of

tableView.tableHeaderView = searchController.searchBar

you don't need to add the searchBar in the tableView or its header.

In your viewDidLoad method you can give the Edge Inset so that the content in tableView is not overlapped by the searchBar

override func viewDidLoad() {
    super.viewDidLoad()

    let edgeInsets = UIEdgeInsetsMake(52, 0, 0, 0)
    self.tableView.contentInset = edgeInsets
    self.tableView.register(UINib(nibName: "AbcCell", bundle: nil), forCellReuseIdentifier: "AbcCell")

}

Following is an image how i have placed it in one of my project and it dosen't float.

在此输入图像描述

我是另一种观点,所以你可以把它放在任何地方

anyView.addSubview(searchController.searchBar)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM