20

I use a NavigationLink to navigate from "View1" to "View2", on the second view, the back button gets the title of the previous view

enter image description here

But, if the title of the previous view is very long, then the back button gets the text "Back"

enter image description here

How could I change that "Back" text?

I wanna make my app available in multiple languages, but it seems that "Back" does not change when phone's language changes

struct ContentView: View {

    var body: some View {

        return NavigationView {
            VStack {
                Text("View1")
                NavigationLink(destination: Text("View2").navigationBarTitle("Title View2", displayMode: .inline)) {
                    Text("NavigationLink")
                }
            }.navigationBarTitle("Title View1")
        }

    }
}

PS: I'd like to keep this functionality as it it, I just want to change the language used for back button

Jawad Ali
  • 13,556
  • 3
  • 32
  • 49
Sorin Lica
  • 6,894
  • 10
  • 35
  • 68
  • use your custom bar button – Nirav Kotecha Jan 20 '20 at 09:44
  • refer to the answer: https://stackoverflow.com/questions/57378744/remove-the-text-from-back-button-in-swiftui – Sanad Barjawi Jan 20 '20 at 10:05
  • 3
    I observed that if application has localizable resources then default *Back* string is translated to current iOS language set in **Settings** (ie. one of supported), but this cannot be overridden (at first I coincidentally translated *Back* string in the same way as system does and thought that in this way it would be possible to substitute *Back*, but nope). – Asperi Jan 20 '20 at 10:39

7 Answers7

9

here is a workaround ....

struct ContentView: View {
        @State private var isActive: Bool = false

        var body: some View {
            NavigationView {
                VStack {
                    NavigationLink(destination: DetailView(), isActive: $isActive) {
                        Text("Title View2")
                    }
                }.navigationBarTitle(! isActive ? "Title View2" : "Your desired back Title", displayMode: .inline)
            }
        }
    }

    struct DetailView: View {
        var body: some View {
            Text("View2")
        }
    }
Jawad Ali
  • 13,556
  • 3
  • 32
  • 49
5

You can create a custom back button in your navigation link by hiding native navigationBackButton. In the custom back button, you can add your translated custom back button title.

struct ContentView: View {

    var body: some View {

        return NavigationView {
            VStack {
                Text("View1")
                NavigationLink("NavigationLink", destination: NextView())
            }.navigationBarTitle("Title View1")
        }
    }
}
struct NextView: View {
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>

    var backButton : some View { Button(action: {
        self.presentationMode.wrappedValue.dismiss()
        }) {
            HStack {
            Image("backImage") // BackButton Image
                .aspectRatio(contentMode: .fit)
                .foregroundColor(.white)
                Text("Go Back") //translated Back button title 
            }
        }
    }
    var body: some View {
            VStack {
            Text("View2")
        }
        .navigationBarTitle("Title View2",displayMode: .inline)
        .navigationBarBackButtonHidden(true)
        .navigationBarItems(leading: backButton)
    }
}

Output:-

enter image description here

forrest
  • 10,570
  • 25
  • 70
  • 132
Manikandan
  • 1,195
  • 8
  • 26
5

I've managed to localize back buttons by providing translations for the Back key in the Localizable.strings file.

I am using SwiftUI though.

Dmytro Grynets
  • 923
  • 11
  • 29
  • 2
    Did you simply added something like `"Back" = "Назад";` in your `Localizable.strings` file? I just did like that, but it's not working for me, although all other strings localizes as expected. – Viesturs Knopkens Feb 13 '21 at 07:39
  • @ViestursKnopkens Yep that worked for me. Make sure that you are setting the locale for your `NavigationView` and not to the contained View – Dmytro Grynets Feb 14 '21 at 16:10
  • I'm setting it with `NavigationView { ... }.environment(\.locale, .init(identifier: "ru"))`. Maybe I'm doing it wrong? – Viesturs Knopkens Feb 15 '21 at 13:04
  • @ViestursKnopkens I'm getting the same issue, did you find out any solution for this? – Muhammad Umair Nov 06 '22 at 07:54
  • Unfortunately no. Although I'm not sure if it's not fixed by now, because recently I haven't done projects which require localization, for that project we just left it like that – "Back" in all languages. Sorry, I can't say anything promising :) – Viesturs Knopkens Nov 10 '22 at 15:40
5

I found a solution which can work also very good.

View1 set a toolbar item with .principal and add your Text or what you want.

for example :

ToolbarItem(placement: .principal) {
    HStack{
        Text("View1")
    }.font(.subheadline)
}

and set also your title in View1:

.navigationTitle("Back")

And do nothing in your view2. it will automatically add your view1 title to your view2 default back button text

Olcay Ertaş
  • 5,987
  • 8
  • 76
  • 112
Osman
  • 1,496
  • 18
  • 22
  • The principal ToolbarItem is a great suggestion, it will work as the default navigation button, but the navigation view doesn't know about the actual title so it has to just show the back button. Although if you want it to match other default titles, the font should be `.headline`, not `.subheadline`. – esthepiking Sep 27 '21 at 18:54
  • This worked better for me than the selected answer, because my base view with the navigation bar was not doing the presentation (a subview was). – Siegfoult Feb 18 '22 at 19:20
1

Create your own button, then assign it using .navigationBarItems(). I found the following format most nearly approximated the default back button.

    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>

    var backButton : some View {
        Button(action: {
            self.presentationMode.wrappedValue.dismiss()
        }) {
            HStack(spacing: 0) {
                Image(systemName: "chevron.left")
                    .font(.title2)
                Text("Cancel")
            }
        }
    }

Make sure you use .navigationBarBackButtonHidden(true) to hide the default button and replace it with your own!

        List(series, id:\.self, selection: $selection) { series in
            Text(series.SeriesLabel)
        }
        .navigationBarBackButtonHidden(true)
        .navigationBarItems(leading: backButton)
J Olson
  • 167
  • 2
  • 8
  • 2
    However, this will break the swipe to go back gesture, which is very important for accessibility and usability. – huwr Feb 19 '23 at 23:38
0

I wouldn't hide the native back button as that would disable things like the back to swipe gesture, or tap-and-hold to select a page.

A better alternative is hiding the back button text, and then adding a custom button, in the child screen:

    .toolbar {
      ToolbarItem(placement: .principal) { Color.clear }
      ToolbarItem(placement: .topBarLeading) {
        Button("Back 2") { dismiss() }.offset(x: -25)
      }
    }

enter image description here

However, if the user tries to tap-and-hold on the new button they won't be able to select a page. Additionally, the -25 is not ideal. Therefore you might be better off with a solution that changes the previous screen's text.


In case you're wondering, it doesn't appear that the ToolbarItem APIs (on the child page) can replace the back button icon/text. Even if you add every single placement, you'll notice that the original back button is intact:

    .toolbar {
      // `Group` used due to 10 limit on views

      // leading
      Group {
        ToolbarItem(placement: .topBarLeading) { Text("L") }
        ToolbarItem(placement: .cancellationAction) { Text("X") }
      }

      // center
      Group {
        ToolbarItem(placement: .principal) { Text("P") }
      }

      // trailing
      Group {
        ToolbarItem(placement: .automatic) { Text("A") }
        ToolbarItem(placement: .navigation) { Text("N") }
        ToolbarItem(placement: .primaryAction) { Text("1") }
        ToolbarItem(placement: .confirmationAction) { Text("C") } // shows in bold
        ToolbarItem(placement: .destructiveAction) { Text("D") }
        ToolbarItem(placement: .topBarTrailing) { Text("T") }
      }

      // trailing but shows "ellipsis.circle" instead
      Group {
        ToolbarItem(placement: .secondaryAction) { Text("2") }
        ToolbarItem(placement: .status) { Text("S") }
      }

      // doesn't appear on the top
      Group {
        ToolbarItem(placement: .keyboard) { Text("K") }
        ToolbarItem(placement: .bottomBar) { Text("B") }
      }
    }

enter image description here

Senseful
  • 86,719
  • 67
  • 308
  • 465
-1

Add localization to your project. If language was set with user device settings(or simulator), after you add localization to your project it will work. Project's supported language must match with selected one on device.

ilnur
  • 865
  • 6
  • 7