Fabio
Fabio

Reputation: 5628

Navigation bar in tableView give mi back space when tapped to scroll on top

When I tap to bring the tableView (This happened with Large Titles) on top, it gives me back a space, which then turn back at the second tap (see image). I try to set tableView.scrollsOnTop = false and add a button to do it... The space go away but the Large titles too, when I pull down they appear again ... Is it an Xcode bug or I'm wrong something? The only solution I have found is to create a dummy view that simulates the original... Any idea? This is my example code:

class TerzoViewController: UITableViewController {

let cellId = "cellId"
let refreshController = UIRefreshControl()

override func viewDidLoad() {
    super.viewDidLoad()

    tableView.backgroundColor = .white
    tableView.delegate = self
    tableView.dataSource = self

    if #available(iOS 10.0, *) {
        tableView.refreshControl = refreshController
    } else {
        tableView.addSubview(refreshController)
    }

    refreshController.tintColor = UIColor(white: 1, alpha: 0.3)
    refreshController.backgroundColor = .clear
    refreshController.attributedTitle = NSAttributedString(string: "Fetching Data...", attributes: [.foregroundColor: UIColor.white, .font: UIFont.systemFont(ofSize: 14, weight: .regular)])
    refreshController.addTarget(self, action: #selector(handleRefresh), for: .valueChanged)

    tableView.register(TableViewCellCustom.self, forCellReuseIdentifier: cellId)
}

@objc fileprivate func handleRefresh() {
    DispatchQueue.main.async {
       self.tableView.refreshControl?.endRefreshing()
        print("Refreshed Data...")
    }
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    configureNavigationBar(largeTitleColor: .white, backgoundColor: .ultraDark, tintColor: .white, title: "Earthquakes", preferredLargeTitle: true)
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 20
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! TableViewCellCustom

    return cell
}

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableView.automaticDimension
}

override func numberOfSections(in tableView: UITableView) -> Int {
    1
}
}

this is my extension to set navigation bar in viewWillAppear:

extension UIViewController {
func configureNavigationBar(largeTitleColor: UIColor, backgoundColor: UIColor, tintColor: UIColor, title: String, preferredLargeTitle: Bool) {
    if #available(iOS 13.0, *) {
        let navBarAppearance = UINavigationBarAppearance()
        navBarAppearance.configureWithOpaqueBackground()
        navBarAppearance.largeTitleTextAttributes = [.foregroundColor: largeTitleColor]
        navBarAppearance.titleTextAttributes = [.foregroundColor: largeTitleColor]
        navBarAppearance.backgroundColor = backgoundColor

        navigationController?.navigationBar.standardAppearance = navBarAppearance
        navigationController?.navigationBar.compactAppearance = navBarAppearance
        navigationController?.navigationBar.scrollEdgeAppearance = navBarAppearance

        navigationController?.navigationBar.prefersLargeTitles = preferredLargeTitle
        navigationItem.largeTitleDisplayMode = .always
        navigationController?.navigationBar.isTranslucent = false
        navigationController?.navigationBar.tintColor = tintColor
        navigationItem.title = title

    } else {
        // Fallback on earlier versions
        navigationController?.navigationBar.barTintColor = backgoundColor
        navigationController?.navigationBar.tintColor = tintColor
        navigationController?.navigationBar.isTranslucent = false
        navigationItem.title = title
    }
}
}

enter image description here

Upvotes: 4

Views: 1014

Answers (1)

Fabio
Fabio

Reputation: 5628

In the absence of a solution, this is the hack to get around the problem:

first disable table view scroll to top:

tableView.scrollsToTop = false

after create a bar button item and call a function that to do it:

navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Top", style: .plain, target: self, action: #selector(handleTop))

now add the function:

@objc fileprivate func handleTop() {
    print("Scroll to top...")
    let indexPath = IndexPath(row: 0, section: 0)
    tableView.scrollToRow(at: indexPath, at: .top, animated: true)
    tableView.setContentOffset(CGPoint(x: 0, y: -1), animated: true)
}

The last row is the hack, if you set contente offset y to -1 the large titles show up correctly and you're done... If you don't insert the last row, the table scroll on top but the large title never show up, it return only when pull down the table...

enter image description here

This is a simply hack but not solve the problem, waiting for someone to explain to me if it is a bug or give me the solution ... This answer complements my question above ... Thanks

Upvotes: 2

Related Questions