How can I avoid the flickering ToolbarItem when switching between tabs, while still keeping a dedicated NavigationStack for each Tab?
I have unsuccessfully tried:
TabView inside another NavigationStack, but that seems to be a bad idea and also breaks switching to a different tab while having a detail view openToolbarItem(id: "SomeId") for both buttons changes nothing.background(.red, in: .capsule) works for the inside of the button, but there's still a border around it that I can't get rid of.buttonStyle(.plain) does nothingstruct MyTabView: View {
var body: some View {
TabView {
Tab {
MyNavStack()
} label: {
Image(systemName: "house")
}
Tab {
MyNavStack()
} label: {
Image(systemName: "star")
}
}
}
}
struct MyNavStack: View {
var body: some View {
NavigationStack {
List {
NavigationLink("Mint", value: Color.mint)
NavigationLink("Pink", value: Color.pink)
}
.navigationDestination(for: Color.self) { color in
Text("You selected \(color.description)")
}
.toolbar {
ToolbarItem(placement: .topBarLeading) {
Button("Flickers") { }
}
}
}
}
}
It seems that the flickering is coming from the "shared background" around the toolbar button.
The flickering can be prevented by hiding the shared background:
ToolbarItem(placement: .topBarLeading) {
Button("Flickers") { }
}
.sharedBackgroundVisibility(.hidden) // ๐ here
However, when this is done, the button no longer looks like a glass button.
You can get it back to a similar appearance by applying a glass button style. It is also necessary to apply .fixedSize, otherwise the button is round and the label is truncated:
ToolbarItem(placement: .topBarLeading) {
Button("Flickers") { }
.fixedSize() // ๐ here
.buttonStyle(.glass) // ๐ and here
}
.sharedBackgroundVisibility(.hidden)
This is close to the appearance that it had without the modifiers, but the button is just a bit smaller.
For better control of the appearance, you can use a custom ButtonStyle:
struct GlassCapsuleButton: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.label
.fixedSize()
.padding(11)
.contentShape(.capsule)
.glassEffect(.clear.interactive(), in: .capsule)
}
}
As a convenience, a ButtonStyle extension can also be defined:
extension ButtonStyle where Self == GlassCapsuleButton {
static var glassCapsule: Self { Self() }
}
Applying the custom button style:
ToolbarItem(placement: .topBarLeading) {
Button("Flickers") { }
.buttonStyle(.glassCapsule) // ๐ here
}
.sharedBackgroundVisibility(.hidden)
