ARTICLE AD BOX
You are asking a number of questions, but they are related. There are also a number of underlying problems.
Why is it required for .navigationTitle() to exist
The reason this works is because it forces the navigation toolbar to be shown, which is used to display the toolbar items. But there are other ways to get it to work. In particular, it works if you add the modifier .toolbarVisibility(.visible, for: .automatic) in combination with a suitable .toolbarTitleDisplayMode, to fit the title being shown.
Why isn't the large title naturally aligning to the leading side?
This would be a question for Apple. It seems that the default alignment for toolbar titles is center. You would need to use a different placement for the toolbar item if you wanted it to be leading-aligned, such as .navigation. However, there may then be other presentation issues to address, such as text truncation and shared glass background.
Another issue is shown on the image below
There was no question here, but I guess you are wondering why both the .largeTitle and .title are being shown together? I found that if you use separate toolbar items for .largeTitle and .subtitle, they switch automatically if you use .toolbarTitleDisplayMode(.automatic).
This brings us on to the problem of the overlap, which is not only seen when navigating to the child view but also when navigating back. I would say, this is a bug (in both cases).
In the first case (when navigating to the child view), a workaround is to change the opacity of the title when the subview is shown. A state variable can be used for this. This state variable needs to be updated in .onAppear and .onDisappear for the subview. Updating in .onDisappear means the title does not re-appear until the subview has disappeared, but this resolves another problem, described below.
Setting the opacity of the title can also be used in the second case too (when navigating back to the parent view). The environment value isPresented can be used to detect when the sub view is no longer presented. This gets reset to false before the transition happens, which is ideal.
The other problem I was referring to above happens if the large title is showing in the parent view when navigating back. The title is first shown with leading alignment, then it jumps to center alignment when the navigation transition completes. I would say, this is another bug.
As a workaround for this last problem, the opacity change that was used to hide the title when the subview was shown can also be used to keep the title hidden until it has moved back to its center position. This is how it works if the state variable is updated in .onDisappear for the subview. It means there is a delay before the title re-appears, but this might be preferable to seeing it jump.
Here is the updated example with all the changes applied:
struct ContentView: View { @State private var isSubviewShowing = false var body: some View { NavigationStack { Screen() .toolbarTitleDisplayMode(.automatic) .toolbarVisibility(.visible, for: .automatic) .toolbar { ToolbarItem(placement: .largeTitle) { Text("First") .font(.largeTitle) .border(Color.black) .opacity(isSubviewShowing ? 0 : 1) } ToolbarItem(placement: .subtitle) { Text("First") .font(.headline) .border(Color.black) } } .navigationDestination(for: Int.self) { integer in DestinationScreen(integer: integer) .onAppear { isSubviewShowing = true } .onDisappear { withAnimation(.easeInOut(duration: 0.5)) { isSubviewShowing = false } } } } } } struct DestinationScreen: View { let integer: Int @Environment(\.isPresented) private var isPresented var body: some View { HStack { Text(integer.description) .font(.largeTitle) Spacer() } .padding() .toolbarTitleDisplayMode(.inlineLarge) .toolbar { ToolbarItem(placement: .largeTitle) { Text(integer.description) .font(.largeTitle) .border(Color.black) .opacity(isPresented ? 1 : 0) } } } } // struct Screen: Unchanged
Just for the record, using the default navigation title might be an altogether simpler way to resolve the issues. This also gives you the leading alignment that you seemed to be wanting.
To get it working this way, just remove the toolbar modifier in both ContentView and DestinationScreen.
