SwiftUI NavigationView上的显示系统后退按钮,没有以前的NavigationLink

时间:2020-09-03 09:27:44

标签: ios swift swiftui

我有一个自定义的SwiftUI标题视图,该视图由多个Text和一个Image组成(为简化起见,省略了Image)。带有标题视图的SwiftUI视图是从UIViewController呈现的,因此我需要一个自定义后退按钮,该按钮从View(正在显示在UIHostingController中)导航到上一个UIViewController展示了它。

我希望此自定义后退按钮看起来与系统后退按钮完全一样,但是,我找不到适合它的正确系统映像。我已经尝试过Image(systemName: "chevron.left")Text("❮")(以及几乎所有其他系统图像和unicode箭头字符),但是这些都不提供系统后退按钮的外观。

有什么方法可以匹配SwiftUI中系统后退按钮的外观吗?

这是系统后退按钮的外观(后退按钮是Unicode左箭头,前导按钮是系统后退按钮): system back button

还有我的自定义后退按钮(如您所见,它比系统按钮小得多): enter image description here

TitleView.swift:

class TitleViewModel: ObservableObject {
    let backAction: () -> ()
    @Published var name: String
    @Published var subtitle: String?

    init(name: String, subtitle: String?, backAction: @escaping () -> ()) {
        self.name = name
        self.subtitle = subtitle
        self.backAction = backAction
    }
}

struct TitleView: ViewModifier {
    @ObservedObject var viewModel: TitleViewModel

    func body(content: Content) -> some View {
        ZStack(alignment: .top) {
            NavigationView {
                VStack {
                    content
                        .navigationBarTitle("", displayMode: .inline)
                        .navigationBarItems(leading: backButton)
                    NavigationLink(destination: Text("Destination").navigationBarItems(trailing: Text("❮")), label: { Text("Next")
                    })
                }
            }
            titleView
        }
    }

    private var backButton: some View {
        Button(action: viewModel.backAction) { Image(systemName: "chevron.left") }
    }

    private var titleView: some View {
        VStack {
            Text(viewModel.name)
            Text(viewModel.subtitle ?? "")
        }
    }
}

extension View {
    func titleView(_ viewModel: TitleViewModel) -> some View {
        modifier(TitleView(viewModel: viewModel))
    }
}

DetailsView.swift

public struct DetailsView: View {
    public var backAction: () -> ()

    public var body: some View {
        Text("Text")
            .titleView(TitleViewModel(name: "Title", subtitle: "SubTitle", backAction: backAction))
    }
}

public class DetailsViewController: UIHostingController<DetailsView> {
    public override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        navigationController?.setNavigationBarHidden(true, animated: false)
    }
}

public struct RootView: View {
    public var next: () -> ()

    public var body: some View {
        VStack {
            Text("Root")
            Button(action: next, label: { Text("Next") })
        }
    }
}

然后在SceneDelegate中,设置一个将UINavigationController表示为UIHostingController

rootViewController

func instantiateRootViewController() -> UIViewController {
    let navigationController = UINavigationController()
    let detailsView = DetailsView(backAction: { navigationController.popViewController(animated: true) })
    let presentDetailsView = { navigationController.pushViewController(DetailsViewController(rootView: detailsView), animated: true) }
    let rootViewController = UIHostingController(rootView: RootView(next: presentDetailsView))
    navigationController.pushViewController(rootViewController, animated: true)
    return navigationController
}

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    if let windowScene = scene as? UIWindowScene {
        let window = UIWindow(windowScene: windowScene)
        let rootViewController = instantiateRootViewController()
        window.rootViewController = rootViewController
        self.window = window
        window.makeKeyAndVisible()
    }
}

1 个答案:

答案 0 :(得分:0)

您可以尝试以下操作:

private var backButton: some View {
    Button(action: {}) {
        Image(systemName: "chevron.left")
            .scaleEffect(0.83)
            .font(Font.title.weight(.medium))
    }
}

您也可以选择应用.offset,但这可能不适用于较大的辅助功能字体大小:

.offset(x: -7, y: 0)