Reputation: 6707
I have several vertically-stacked two pairs of rectangles (Rectangle()
), each of which has a Button
. When the user taps a button, the user needs to be forwarded to a specific View
. For instance, if they tap Alice, the user needs to be forwarded to AliceView.
If it's just the matter of one button, forwarding the user from the current View
to another isn't a problem. Anyway, the following is what I have.
import SwiftUI
struct ContentView: View {
@State var canAlice: Bool = false
@State var canKim: Bool = false
var body: some View {
NavigationView {
List {
HStack(spacing: 0) {
// ZStack: A view that overlays its children, aligning them in both axes.
ZStack {
Rectangle().frame(width: UIScreen.screenWidth / 2.0, height: UIScreen.screenWidth / 2.0, alignment: .topLeading)
.foregroundColor(.orange)
.border(Color.yellow, width: 2)
Button(action: {
self.canAlice = true
}, label: {
Text("Alice")
.font(.largeTitle)
.background(Color.black)
.foregroundColor(.white)
})
NavigationLink(destination: AliceView(), isActive: $canAlice) { EmptyView() }
}
ZStack {
Rectangle().frame(width: UIScreen.screenWidth / 2.0, height: UIScreen.screenWidth / 2.0, alignment: .topLeading)
.foregroundColor(.orange)
.border(Color.yellow, width: 2)
Button(action: {
self.canKim = true
}, label: {
Text("Kim")
.font(.largeTitle)
.background(Color.black)
.foregroundColor(.white)
})
NavigationLink(destination: KimView(), isActive: $canKim) { EmptyView() }
}
}.listRowInsets(EdgeInsets())
HStack(spacing: 0) {
...
...
...
}.listRowInsets(EdgeInsets())
HStack(spacing: 0) {
...
...
...
}.listRowInsets(EdgeInsets())
HStack(spacing: 0) {
...
...
...
}.listRowInsets(EdgeInsets())
}
.edgesIgnoringSafeArea(.all)
.statusBar(hidden: true)
}
}
}
Now, if I tap the Alice button, the current View
transitions to AliceView, comes back to the current View
and then transitions to KimView. How can I have multiple buttons within a single View
and forward the user to respective View
s? I'm new to SwiftUI. Thanks.
UPDATE
import SwiftUI
struct ContentView: View {
@State private var selection: Int? = 0
var body: some View {
NavigationView {
List {
HStack(spacing: 0) {
// ZStack: A view that overlays its children, aligning them in both axes.
ZStack {
Rectangle().frame(width: UIScreen.screenWidth / 2.0, height: UIScreen.screenWidth / 2.0, alignment: .topLeading)
.foregroundColor(.orange)
.border(Color.yellow, width: 2)
Button(action: {
self.selection = 1
}, label: {
Text("Alice")
.font(.largeTitle)
.background(Color.black)
.foregroundColor(.white)
})
NavigationLink(destination: AliceView(), tag: 1, selection: self.$selection) { EmptyView() }
}
ZStack {
Rectangle().frame(width: UIScreen.screenWidth / 2.0, height: UIScreen.screenWidth / 2.0, alignment: .topLeading)
.foregroundColor(.orange)
.border(Color.yellow, width: 2)
Button(action: {
self.selection = 2
}, label: {
Text("Kim")
.font(.largeTitle)
.background(Color.black)
.foregroundColor(.white)
})
NavigationLink(destination: KimView(), tag: 2, selection: self.$selection) { EmptyView() }
}
}.listRowInsets(EdgeInsets())
HStack(spacing: 0) {
...
...
...
}.listRowInsets(EdgeInsets())
HStack(spacing: 0) {
...
...
...
}.listRowInsets(EdgeInsets())
HStack(spacing: 0) {
...
...
...
}.listRowInsets(EdgeInsets())
}
.edgesIgnoringSafeArea(.all)
.statusBar(hidden: true)
}
}
}
Now, when I tap Alice or Kim, I won't transition to another view and then bounce back to the initial view. Whether I tap Alice or Kim, I transition to AliceView.
Upvotes: 2
Views: 91
Reputation: 257563
Here is a solution (by approach referenced in comment). Tested with Xcode 11.4 / iOS 13.4
Button style to hide a link:
struct LinkButtonStyle<D: View>: ButtonStyle {
let destination: D
@Binding var isActive: Bool
func makeBody(configuration: Configuration) -> some View {
configuration.label
.background(NavigationLink(destination: self.destination, isActive: $isActive) { EmptyView() })
}
}
and an example of modified cell
ZStack {
Rectangle().frame(width: UIScreen.screenWidth / 2.0, height: UIScreen.screenWidth / 2.0, alignment: .topLeading)
.foregroundColor(.orange)
.border(Color.yellow, width: 2)
Button(action: {
self.canAlice = true
}, label: {
Text("Alice")
.font(.largeTitle)
.background(Color.black)
.foregroundColor(.white)
}).buttonStyle(LinkButtonStyle(destination: AliceView(), isActive: $canAlice))
}
Upvotes: 1
Reputation: 16341
You could achieve this using a single Bool
for isActice
parameter and a single NavigationLink
. Also need to add a destination parameter outside the body
. And set the destination in the button action. Here's an example:
struct ContentView: View {
@State var showNextView = false
var destination = GeorgeView()
var body: some View {
NavigationView {
List {
HStack(spacing: 0) {
NavigationLink(destination: destination, isActive: $showNextView) { EmptyView() }
// Rest of your implementation...
Button(action: {
self.destination = KimView()
self.showNextView = true
}, label: {
Text("Kim")
.font(.largeTitle)
.background(Color.black)
.foregroundColor(.white)
})
}
}
}
}
}
Upvotes: 0