Skip to content

Instantly share code, notes, and snippets.

@Coder-ACJHP
Last active April 3, 2024 12:38
Show Gist options
  • Save Coder-ACJHP/4d7f70795e0777dd7fa24943161b37e0 to your computer and use it in GitHub Desktop.
Save Coder-ACJHP/4d7f70795e0777dd7fa24943161b37e0 to your computer and use it in GitHub Desktop.
How to Add a UINavigationBar Without a UINavigationBarController programmatically (supports large title animated also)
class NavBarTestViewController: UIViewController, UINavigationBarDelegate, UIScrollViewDelegate {
private let navBar: UINavigationBar = {
let navBar = UINavigationBar()
navBar.translatesAutoresizingMaskIntoConstraints = false
return navBar
}()
private let vScrollView: UIScrollView = {
let scrollView = UIScrollView(frame: .zero)
scrollView.bounces = true
scrollView.alwaysBounceVertical = true
scrollView.alwaysBounceHorizontal = false
scrollView.showsVerticalScrollIndicator = false
scrollView.showsHorizontalScrollIndicator = false
scrollView.contentInsetAdjustmentBehavior = .never
scrollView.backgroundColor = .clear
scrollView.translatesAutoresizingMaskIntoConstraints = false
return scrollView
}()
internal let bodyView: UIView = {
let view = UIView(frame: .zero)
view.backgroundColor = .clear
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
private let buttonsAction: Selector = {
return #selector(handleButtonPress(_:))
}()
private lazy var settingsButton: UIBarButtonItem = {
let icon = UIImage(named: "icon.cog.filled")?.withRenderingMode(.alwaysTemplate)
let rightItem = UIBarButtonItem(image: icon, style: .plain, target: self, action: buttonsAction)
rightItem.tintColor = UIColor(hexString: "#642F58")
return rightItem
}()
private var oldValue = false
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor(hexString: "#FDEFF8")
addSubViews()
setupNavBar()
}
private final func setupNavBar() {
navBar.delegate = self
navBar.prefersLargeTitles = true
navBar.barTintColor = UIColor(hexString: "#FEF5FB")
navBar.titleTextAttributes = [
.foregroundColor: UIColor(hexString: "#6A315A"),
.font: Fonts.default.semibold.withSize(18)
]
navBar.largeTitleTextAttributes = [
.foregroundColor: UIColor(hexString: "#6A315A"),
.font: Fonts.default.bold.withSize(30)
]
let navigationItem = UINavigationItem(title: "Community")
navigationItem.largeTitleDisplayMode = .always
navBar.setItems([navigationItem], animated: false)
}
private final func addSubViews() {
view.addSubview(navBar)
view.addSubview(vScrollView)
vScrollView.addSubview(bodyView)
vScrollView.delegate = self
NSLayoutConstraint.activate([
navBar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
navBar.leadingAnchor.constraint(equalTo: view.leadingAnchor),
navBar.trailingAnchor.constraint(equalTo: view.trailingAnchor),
navBar.heightAnchor.constraint(greaterThanOrEqualToConstant: Constants.navigationBarXdevicesHeight), // 44 point
vScrollView.topAnchor.constraint(equalTo: navBar.bottomAnchor),
vScrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
vScrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
vScrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
bodyView.topAnchor.constraint(equalTo: vScrollView.topAnchor),
bodyView.leadingAnchor.constraint(equalTo: vScrollView.leadingAnchor),
bodyView.trailingAnchor.constraint(equalTo: vScrollView.trailingAnchor),
bodyView.bottomAnchor.constraint(equalTo: vScrollView.bottomAnchor),
bodyView.widthAnchor.constraint(equalTo: vScrollView.widthAnchor)
])
let bodyViewHeight = bodyView.heightAnchor.constraint(equalToConstant: 1500)
bodyViewHeight.priority = UILayoutPriority(rawValue: 250)
bodyViewHeight.isActive = true
}
func position(for bar: UIBarPositioning) -> UIBarPosition {
.topAttached
}
@objc
private final func handleButtonPress(_ sender: UIButton) {
if sender == settingsButton {
print("settingsButton")
}
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let needsToShowLargeTitle = scrollView.contentOffset.y <= 64
if needsToShowLargeTitle != oldValue {
navBar.items?.first?.largeTitleDisplayMode = needsToShowLargeTitle ? .always : .never
navBar.items?.first?.rightBarButtonItem = needsToShowLargeTitle ? nil : settingsButton
self.oldValue = needsToShowLargeTitle
UIView.animate(withDuration: 0.25, animations: {
self.navBar.layoutIfNeeded()
self.view.layoutIfNeeded()
})
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment