Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to turn off adjusting large titles by UITableView in iOS 11?

There's this large titles feature in iOS 11 that shows large title when the UITableViewController's table is scrolled to top, and gets collapsed to standard small title when the user scrolls the table away from top. This is standard behavior. I need the navigation controller to behave a bit differently - I need to always show the large title. How to achieve this?

Following code does not help, it still collapses when scrolled.

navigationController?.navigationBar.prefersLargeTitles = true
navigationItem.largeTitleDisplayMode = .always
like image 438
Milan Nosáľ Avatar asked Sep 30 '17 19:09

Milan Nosáľ


3 Answers

I've achieved it unintentionally when embedded UITableViewController inside UIViewController.

I'm not sure whether it is an Apple's bug or intended behavior.

So stack is as simple as UINavigationController -> UIViewController(used as container) -> UITableViewController

Here is sample of view controller with embedded UITableViewController fullscreen

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    var vc = UITableViewController(style: .plain)
    var array: [String] = []

    override func viewDidLoad() {
        super.viewDidLoad()

        vc.view.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(vc.view)
        view.addConstraint(view.leadingAnchor.constraint(equalTo: vc.view.leadingAnchor))
        view.addConstraint(view.rightAnchor.constraint(equalTo: vc.view.rightAnchor))
        view.addConstraint(view.safeAreaLayoutGuide.topAnchor.constraint(equalTo: vc.view.topAnchor))
        view.addConstraint(view.bottomAnchor.constraint(equalTo: vc.view.bottomAnchor))

        vc.tableView.delegate = self
        vc.tableView.dataSource = self

        array = "0123456789".characters.map(String.init)
        vc.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "identifier")

        title = "Title"
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return array.count
    }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "identifier", for: indexPath)
        cell.textLabel?.text = array[indexPath.row]
        return cell
    }
}

Here is the result

enter image description here

Hope it helps.

P.S. Surprisingly, my current problem is that I don't know how to get collapsing behavior with such architecture :)

like image 92
Sander Avatar answered Nov 15 '22 04:11

Sander


What I did was to add another view between navigationBar and TableView with a height of 1.

let tableViewSeperator: UIView = {
    let view = UIView()
    // remove the color, so it wont be visible.
    view.backgroundColor = UIColor.systemBlue 
    view.translatesAutoresizingMaskIntoConstraints = false
    return view
 }()

One thing which is important is add this seperator view as a subview of your viewcontroller's view before tableView, otherwise it won't work

view.addSubview(tableViewSeperator)
view.addSubview(tableView)

or if you want to save one line of code, you can also do it like this.

[tableViewSeperator, tableView].forEach({view.addSubview($0)})

Then set its constraints like this.

tableViewSeperator.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true
tableViewSeperator.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive = true        
tableViewSeperator.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 0).isActive = true
tableViewSeperator.heightAnchor.constraint(equalToConstant: 1).isActive = true

The last thing is change the tableView TopAnchor to be the BottomAnchor of sperator View.

tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true
tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive = true
tableView.topAnchor.constraint(equalTo: tableViewSeperator.bottomAnchor, constant: 0).isActive = true
tableView.bottomAnchor.constraint(equalTo: createItemBtn.topAnchor, constant: 0).isActive = true

Now when you scroll the the NavigationBar will stay as Large.

like image 23
Simran Singh Avatar answered Nov 15 '22 05:11

Simran Singh


You need to add UIView(it's can be width=0, height=0) before add UITableView.

example

Then this code will work

navigationController?.navigationBar.prefersLargeTitles = true
navigationItem.largeTitleDisplayMode = .always
like image 22
Fedy_ Avatar answered Nov 15 '22 03:11

Fedy_