从 SwiftUI 中的导航栏中删除后退按钮文本
Posted
技术标签:
【中文标题】从 SwiftUI 中的导航栏中删除后退按钮文本【英文标题】:Remove back button text from navigationbar in SwiftUI 【发布时间】:2020-06-17 01:21:01 【问题描述】:我最近开始使用 SwiftUI,得出的结论是使用导航还不是很好。我想要达到的目标如下。我终于设法摆脱了半透明背景而不会导致应用程序崩溃,但现在我遇到了下一个问题。如何摆脱 navbaritem 中的“后退”文本?
我通过像这样在SceneDelegate.swift
文件中设置默认外观来实现上述视图。
let newNavAppearance = UINavigationBarAppearance()
newNavAppearance.configureWithTransparentBackground()
newNavAppearance.setBackIndicatorImage(UIImage(named: "backButton"), transitionMaskImage: UIImage(named: "backButton"))
newNavAppearance.titleTextAttributes = [
.font: UIFont(name: GTWalsheim.bold.name, size: 18)!,
.backgroundColor: UIColor.white
]
UINavigationBar.appearance().standardAppearance = newNavAppearance
我可以实现此目的的一种可能方法是覆盖导航栏项目,但是正如此问题的创建者已经说过的那样,这有一个缺点(SwiftUI Custom Back Button Text for NavigationView),在您覆盖导航栏项目后,后退手势停止工作.有了这个,我也想知道如何设置后退按钮的前景颜色。它现在具有默认的蓝色,但是我想用另一种颜色覆盖它。
【问题讨论】:
【参考方案1】:其实很简单。以下解决方案是我制作的最快和最干净的解决方案。
例如,将其放在 SceneDelegate 的底部。
extension UINavigationController
// Remove back button text
open override func viewWillLayoutSubviews()
navigationBar.topItem?.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
这将从您应用中的每个 NavigationView (UINavigationController) 中删除后退按钮文本。
【讨论】:
谢谢!几天来,我一直在寻找像这样的简单解决方案。 这应该是公认的答案。【参考方案2】:支持@Pitchbloas 提供的解决方案,此方法只需将backButtonDisplayMode
属性设置为.minimal
:
extension UINavigationController
open override func viewWillLayoutSubviews()
navigationBar.topItem?.backButtonDisplayMode = .minimal
【讨论】:
我不知道'backButtonDisplayMode',谢谢! 这是一个不错的选择!只是提醒其他人它需要 ios 14+。 发现这是一个很好的解决方案,但应该在设置按钮显示模式之前调用super.viewWillLayoutSubviews()
【参考方案3】:
我找到了一种直接使用 SwiftUI 删除后退按钮文本并保留原始 V 形的简单方法。
添加了拖动手势以模仿经典的导航返回按钮 当用户想要通过向右滑动返回时。
import SwiftUI
struct ContentView: View
@Environment(\.presentationMode) var presentation
var body: some View
ZStack
// Your main view code here with a ZStack to have the
// gesture on all the view.
.navigationBarBackButtonHidden(true)
.navigationBarItems(
leading: Button(action: presentation.wrappedValue.dismiss() )
Image(systemName: "chevron.left")
.foregroundColor(.blue)
.imageScale(.large) )
.contentShape(Rectangle()) // Start of the gesture to dismiss the navigation
.gesture(
DragGesture(coordinateSpace: .local)
.onEnded value in
if value.translation.width > .zero
&& value.translation.height > -30
&& value.translation.height < 30
presentation.wrappedValue.dismiss()
)
【讨论】:
这太棒了!我要提一下,presentation.wrappedValue.dismiss 在项目中一直很头疼,有时会在特定情况下导致应用崩溃。【参考方案4】:所以我实际上最终得到了以下实际可行的解决方案。我正在像这样覆盖导航栏项目
.navigationBarItems(leading:
Image("backButton")
.foregroundColor(.blue)
.onTapGesture
self.presentationMode.wrappedValue.dismiss()
)
唯一的问题是后退手势不起作用,因此通过实际扩展 UINavigationController
解决了这个问题
extension UINavigationController: UIGestureRecognizerDelegate
override open func viewDidLoad()
super.viewDidLoad()
interactivePopGestureRecognizer?.delegate = self
public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool
return viewControllers.count > 1
现在它看起来正是我想要的方式,解决方案有点老套......但它现在可以工作,希望 SwiftUI 会成熟一点,这样可以更容易地完成。
【讨论】:
这不会在向后滑动时为您提供重复的导航和返回按钮吗?对我来说就是这样。所以我最终使用工具栏增加了导航标题的宽度。【参考方案5】:标准返回按钮标题取自前一屏的导航栏标题。
可以通过以下方法获得所需的效果:
struct TestBackButtonTitle: View
@State private var hasTitle = true
var body: some View
NavigationView
NavigationLink("Go", destination:
Text("Details")
.onAppear
self.hasTitle = false
.onDisappear
self.hasTitle = true
)
.navigationBarTitle(self.hasTitle ? "Master" : "")
【讨论】:
好吧,是的,这是一个可能的解决方案,但它真的很讨厌,如果我必须在每个屏幕上都这样做,那会有点烦人和 hacky。我正在寻找一种全局禁用此文本的方法。【参考方案6】:自定义 navigationBarItems 和 self.presentationMode.wrappedValue.dismiss() 有效,但不允许执行向后滑动
您可以添加以下代码以再次滑动
//perform gesture go back
extension UINavigationController: UIGestureRecognizerDelegate
override open func viewDidLoad()
super.viewDidLoad()
interactivePopGestureRecognizer?.delegate = self
public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool
return viewControllers.count > 1
但问题是,有时它会在你滑动半屏然后取消时让你的应用崩溃。
我建议使用另一种方法来删除“后退”文本。 添加 isActive 状态来监控当前屏幕是否处于活动状态。 :)
struct ContentView: View
@State var isActive = false
var body: some View
NavigationView()
NavigationLink(
"Next",
destination: Text("Second Page").navigationBarTitle("Second"),
isActive: $isActive
)
.navigationBarTitle(!isActive ? "Title" : "", displayMode: .inline)
【讨论】:
在 iOS 15.2 上,此(使用 $isActive 绑定的第二个修复)可以禁用后退按钮文本,但会导致在导航中选择随机项目,并且调试控制台显示错误“遇到 SwiftUI推送导航链接时出现问题。请提交错误。"【参考方案7】:使用这个:
import UIKit
extension UINavigationController
open override func viewWillAppear(_ animated: Bool)
super.viewWillAppear(animated)
navigationBar.topItem?.backButtonDisplayMode = .minimal
这比viewWillLayoutSubviews
变体更高效(如果您print
viewWillLayoutSubviews
解决方案中的任何内容被打印了很多次,您可以自己检查一下。
【讨论】:
【参考方案8】:使用Introspect 框架,您可以轻松访问底层导航项并将backButtonDisplayMode
设置为最小。
这是在被推送的视图中使用它的方法
var body: some View
Text("Your body here")
.introspectNavigationController navController in
navController.navigationBar.topItem?.backButtonDisplayMode = .minimal
【讨论】:
以上是关于从 SwiftUI 中的导航栏中删除后退按钮文本的主要内容,如果未能解决你的问题,请参考以下文章