El Tomato
El Tomato

Reputation: 6707

View With Multiple Buttons To Go Respective Forwarding Views

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.

enter image description here

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 Views? 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

Answers (2)

Asperi
Asperi

Reputation: 257563

Here is a solution (by approach referenced in comment). Tested with Xcode 11.4 / iOS 13.4

enter image description here

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

Frankenstein
Frankenstein

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

Related Questions