SwiftiSwift
SwiftiSwift

Reputation: 8767

Custom Back Button Text for NavigationView

How can I change the back button text in a NavigationView when a new View is pushed?

The default shows "Back" but I want to change it to something.

Is that currently possible in SwiftUI?

Upvotes: 5

Views: 4061

Answers (2)

Vadim Ahmerov
Vadim Ahmerov

Reputation: 777

SwiftUI doesn't support this directly, but you can work around it by manually locating the UINavigationController and updating the navigation item for the top UIViewController.

I've created a user-friendly View extension to make this easier:

extension View {
    func backBarButtonTitle(_ title: String) -> some View {
        modifier(BackButtonModifier(title: title))
    }
}

// MARK: - BackButtonModifier

struct BackButtonModifier: ViewModifier {
    let title: String

    func body(content: Content) -> some View {
        content.background(BackButtonTitleView(title: title))
    }
}

// MARK: - BackButtonTitleView

private struct BackButtonTitleView: UIViewRepresentable {
    let title: String

    func makeUIView(context _: Context) -> BackButtonTitleUIView {
        BackButtonTitleUIView(title: title)
    }

    func updateUIView(_: BackButtonTitleUIView, context _: Context) {}
}

// MARK: - BackButtonTitleUIView

private final class BackButtonTitleUIView: UIView {
    // MARK: Lifecycle

    init(title: String) {
        self.title = title
        super.init(frame: .zero)
    }

    required init?(coder _: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    // MARK: Internal

    override func layoutSubviews() {
        super.layoutSubviews()
        if didConfigureTitle {
            return
        }
        let topNavigationItem = searchNavigationController(currentResponder: self)?
            .topViewController?
            .navigationItem
        if let topNavigationItem {
            topNavigationItem.backButtonTitle = title
            didConfigureTitle = true
        }
    }

    // MARK: Private

    private let title: String
    private var didConfigureTitle = false

    private func searchNavigationController(currentResponder: UIResponder) -> UINavigationController? {
        if let navigationController = currentResponder as? UINavigationController {
            return navigationController
        } else if let nextResponder = currentResponder.next {
            return searchNavigationController(currentResponder: nextResponder)
        } else {
            return nil
        }
    }
}

Upvotes: 0

Md. Ashikur Rahman
Md. Ashikur Rahman

Reputation: 541

Full Code:

struct SampleDetails: View {
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>

    var btnBack: some View {
        Button(action: {self.presentationMode.wrappedValue.dismiss()}) {
            HStack {
                Image("ic_back") // set image here
                .aspectRatio(contentMode: .fit)
                .foregroundColor(.white)
                Text("Go back")
            }
        }
    }

    var body: some View {
        List {
            Text("sample code")
        }
        .navigationBarBackButtonHidden(true)
        .navigationBarItems(leading: btnBack)
    }
}

For more clarification click here.

Upvotes: 7

Related Questions