There are 2 options that I'm aware of.
1) Related to Move UINavigationController's toolbar to the top to lie underneath navigation bar
You can subclass UINavigationController and change the Y-axis position of the toolbar when the value is set.
import UIKit
private var context = 0
class NavigationController: UINavigationController {
private var inToolbarFrameChange = false
var observerBag: [NSKeyValueObservation] = []
override func awakeFromNib() {
super.awakeFromNib()
self.inToolbarFrameChange = false
}
override func viewDidLoad() {
super.viewDidLoad()
observerBag.append(
toolbar.observe(\.center, options: .new) { toolbar, _ in
if !self.inToolbarFrameChange {
self.inToolbarFrameChange = true
toolbar.frame = CGRect(
x: 0,
y: self.navigationBar.frame.height + UIApplication.shared.statusBarFrame.height,
width: toolbar.frame.width,
height: toolbar.frame.height
)
self.inToolbarFrameChange = false
}
}
)
}
override func setToolbarHidden(_ hidden: Bool, animated: Bool) {
super.setToolbarHidden(hidden, animated: false)
var rectTB = self.toolbar.frame
rectTB = .zero
}
}
2) You can create your own UIToolbar and add it to view of the UIViewController. Then, you add the constraints to the leading, trailing and the top of the safe area.
import UIKit
final class ViewController: UIViewController {
private let toolbar = UIToolbar()
private let segmentedControl: UISegmentedControl = {
let control = UISegmentedControl(items: ["Op 1", "Op 2"])
control.isEnabled = false
return control
}()
override func loadView() {
super.loadView()
setupToolbar()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.navigationBar.hideBorderLine()
}
private func setupToolbar() {
let barItem = UIBarButtonItem(customView: segmentedControl)
toolbar.setItems([barItem], animated: false)
toolbar.isTranslucent = false
toolbar.isOpaque = false
view.addSubview(toolbar)
toolbar.translatesAutoresizingMaskIntoConstraints = false
toolbar.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
toolbar.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
toolbar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
}
}
private extension UINavigationBar {
func showBorderLine() {
findBorderLine().isHidden = false
}
func hideBorderLine() {
findBorderLine().isHidden = true
}
private func findBorderLine() -> UIImageView! {
return self.subviews
.flatMap { $0.subviews }
.compactMap { $0 as? UIImageView }
.filter { $0.bounds.size.width == self.bounds.size.width }
.filter { $0.bounds.size.height <= 2 }
.first
}
}