Reputation: 147
I am using MVVM+C pattern to build my app. Currently I am facing a problem with changing the native back button title and image of navigation bar to the custom image without the title. I've tried a lots of solutions what I was able to find, but nothing set the different title or even an image. I've ended up with this code in AppDelegate.swift:
let navigationController: UINavigationController = .init()
if #available(iOS 13.0, *) {
let appearence = UINavigationBarAppearance()
appearence.configureWithOpaqueBackground()
appearence.backgroundColor = .backgroundColor
appearence.shadowColor = nil
appearence.shadowImage = nil
navigationController.navigationBar.standardAppearance = appearence
navigationController.navigationBar.scrollEdgeAppearance = navigationController.navigationBar.standardAppearance
} else {
navigationController.navigationBar.isTranslucent = false
navigationController.navigationBar.barTintColor = .backgroundColor
navigationController.navigationBar.shadowImage = nil
navigationController.navigationBar.shadowColor = nil
}
// This code is not working at all, always get "Back" as a default with default image =====
let backButtonBackgroundImage = UIImage(named: "backButton")
navigationController.navigationBar.backIndicatorImage = backButtonBackgroundImage
navigationController.navigationBar.backIndicatorTransitionMaskImage = backButtonBackgroundImage
let backBarButtton = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
navigationController.navigationItem.backBarButtonItem = backBarButtton
// =========
navigationController.navigationBar.tintColor = .primary
window?.rootViewController = navigationController
window?.makeKeyAndVisible()
Also, I've followed the official documentation but without any success. As default I've set the navigation bar as hidden (because is not needed for multiple times) and I am showing it in ViewWillAppear
and hiding in ViewWillDisappear
methods.
Is there someone who has an idea of what's going on? Thanks!
This is what I get with the new code:
SOLUTION: After using code from Scott I was able to change the image and look of the navigation bar but I lost the ability to swipe back. After adding this code to the UINavigationBar extension I was able to get it back:
extension UINavigationController: UIGestureRecognizerDelegate {
@objc func goBack(sender: Any?) {
self.popViewController(animated: true)
}
override open func viewDidLoad() {
super.viewDidLoad()
interactivePopGestureRecognizer?.delegate = self
}
public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
return viewControllers.count > 1
}
}
Upvotes: 0
Views: 656
Reputation: 23701
Below is some Playground code that shows a UINavigationController
with a custom back button that is an image.
Note that what it does is hides the system provided back button, then substitutes another button that still performs the "back" action but on a custom UINavigationController
.
There may be a more efficient way to duplicate the functionality of "back" that doesn't involve a custom class and a custom target-action setup, but I couldn't find one quickly so finding that solution can be left as an exercise for the reader.
import UIKit
import SwiftUI
import PlaygroundSupport
NSSetUncaughtExceptionHandler { error in
debugPrint(error)
}
class MyNavController : UINavigationController {
@objc func goBack(sender: Any?) {
self.popViewController(animated: true)
}
}
let navDestination1 = UIViewController()
navDestination1.navigationItem.title = "Destination 1"
let navigationController = MyNavController(rootViewController: navDestination1)
if #available(iOS 13.0, *) {
let appearence = UINavigationBarAppearance()
appearence.configureWithOpaqueBackground()
appearence.backgroundColor = .purple
appearence.shadowColor = nil
appearence.shadowImage = nil
navigationController.navigationBar.standardAppearance = appearence
navigationController.navigationBar.scrollEdgeAppearance = navigationController.navigationBar.standardAppearance
} else {
navigationController.navigationBar.isTranslucent = false
navigationController.navigationBar.barTintColor = .purple
navigationController.navigationBar.shadowImage = nil
}
let navDestination2 = UITableViewController()
navDestination2.navigationItem.title = "Destination 2"
navDestination2.navigationItem.hidesBackButton = true
navDestination2.navigationItem.leftBarButtonItem = UIBarButtonItem(
image: UIImage(systemName: "multiply.circle.fill"),
style: UIBarButtonItem.Style.done,
target: navigationController,
action: #selector(MyNavController.goBack))
navigationController.pushViewController(navDestination2, animated: true)
navigationController.view.bounds = CGRect(x: 0,y: 0,width: 320,height: 480)
PlaygroundSupport.PlaygroundPage.current.liveView = navigationController
Upvotes: 1