使用 MVVM+C 更改导航栏的后退按钮
Changing the back button of UINavigaitonBar with MVVM+C
我正在使用 MVVM+C 模式构建我的应用程序。目前,我面临将导航栏的本机后退按钮标题和图像更改为没有标题的自定义图像的问题。我尝试了很多我能找到的解决方案,但没有设置不同的标题甚至图像。我在 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()
此外,我已经按照 official documentation 进行操作,但没有任何成功。默认情况下,我将导航栏设置为隐藏(因为多次不需要),我在 ViewWillAppear
中显示它并隐藏在 ViewWillDisappear
方法中。
有人知道发生了什么事吗?谢谢!
这段代码的结果:
预期结果:
这是我使用新代码得到的结果:
解决方案:
使用 Scott 的代码后,我能够更改导航栏的图像和外观,但无法向后滑动。将此代码添加到 UINavigationBar 扩展后,我能够取回它:
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
}
}
下面是一些 Playground 代码,其中显示了 UINavigationController
和自定义后退按钮,该按钮是一个图像。
请注意,它所做的是隐藏系统提供的后退按钮,然后替换为另一个仍执行“后退”操作但在自定义 UINavigationController
上的按钮。
可能有一种更有效的方法来复制不涉及自定义 class 和自定义目标操作设置的“后退”功能,但我无法快速找到一个所以找到该解决方案可以留作 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
我正在使用 MVVM+C 模式构建我的应用程序。目前,我面临将导航栏的本机后退按钮标题和图像更改为没有标题的自定义图像的问题。我尝试了很多我能找到的解决方案,但没有设置不同的标题甚至图像。我在 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()
此外,我已经按照 official documentation 进行操作,但没有任何成功。默认情况下,我将导航栏设置为隐藏(因为多次不需要),我在 ViewWillAppear
中显示它并隐藏在 ViewWillDisappear
方法中。
有人知道发生了什么事吗?谢谢!
这段代码的结果:
预期结果:
这是我使用新代码得到的结果:
解决方案: 使用 Scott 的代码后,我能够更改导航栏的图像和外观,但无法向后滑动。将此代码添加到 UINavigationBar 扩展后,我能够取回它:
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
}
}
下面是一些 Playground 代码,其中显示了 UINavigationController
和自定义后退按钮,该按钮是一个图像。
请注意,它所做的是隐藏系统提供的后退按钮,然后替换为另一个仍执行“后退”操作但在自定义 UINavigationController
上的按钮。
可能有一种更有效的方法来复制不涉及自定义 class 和自定义目标操作设置的“后退”功能,但我无法快速找到一个所以找到该解决方案可以留作 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