In swiftUI is it possible to add a new view onto the screen with a button?

别来无恙 提交于 2021-01-27 13:23:51

问题


Every time I Tap the button I would like a new cardView to appear. I am wondering if this is possible in swiftUI and if so what action I would need to do it. It would be even better if I am able to pass some parameters in to the cardView struct but any help would be great!


struct ContentView: View {
    var body: some View {
        ZStack {
            VStack {
                TextButton(action: {print("Button tapped")}, text: "new card")
                CardView()
            }
        }
    }
}

struct CardView: View {
    var body: some View {
        ZStack {
            Rectangle()
                .fill(Color(#colorLiteral(red: 0.7450980544, green: 0.1568627506, blue: 0.07450980693, alpha: 1)))
                .frame(width: 100, height: 100 * 1.618)
                .cornerRadius(16)
                .shadow(color: Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)).opacity(0.1), radius: 1, x: 0, y: 1)
                .shadow(color: Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)).opacity(0.2), radius: 10, x: 0, y: 10)

            VStack {
                Text("Card")
                    .font(.system(size: 10) )
                    .foregroundColor(.white)
                    .bold()
            }
        }
    }
}


struct TextButton: View {
    let action: () -> Void
    let text: String

    var body: some View {
        Button(action: action, label: {
            Text(text)
                .padding(.horizontal, 16)
                .padding(.vertical, 16)
                .foregroundColor(.white)
                .background(Color.blue)
                .cornerRadius(.infinity)
                .shadow(color: Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)).opacity(0.1), radius: 1, x: 0, y: 1)
                .shadow(color: Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)).opacity(0.2), radius: 10, x: 0, y: 10)
        })
    }
}
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
} ```

回答1:


In SwiftUI, the View reflects the State data, so you don't modify the View directly, but rather modify the State data, and build the View based on the State. This is a core principle behind SwiftUI, and it allows you to separate the View concerns from the data that drives it (ViewModel in some lingo).

So, let's assume that we have a data model for a Card (make it conform to Identifiable - this will be needed later):

struct Card: Identifiable {
  let id = UUID()
  let name: String
}

And let's define an array of cards as a state variable in your View:

@State private var cards: [Card] = [Card(name: "foo")]

Then the body could display these cards with a ForEach or in a List view:

var body = some View {
  VStack() {
    Button("Add Card") {
       self.cards.append(Card(name: "I'm an added card"))
    }
    ForEach(cards) { card in
       CardView(for: card) // if your CardView had parameters
    }
  }
}

What happens is that the closure for the button adds a new Card instance to the cards state variable. That's it. It doesn't change anything in the View directly. The View sees the change (that's what SwiftUI does behind the scenes) and re-renders itself.

The reason you needed a Card to conform to Identifiable was to let the ForEach know how to uniquely identify each card. Without conforming to identifiable, you could use a key path like so:

ForEach(cards, id: \.self) { card in
  // ...
}



回答2:


check this out:

import SwiftUI

struct ContentView: View {

    @State var cards: [CardView] = [CardView()]



    var body: some View {
        VStack {
            TextButton(action: {
                print("Button tapped")
                self.cards.append(CardView())

            }, text: "new card")
            ZStack {
                ForEach(cards, id: \.self) { card in
                    card
                        .rotationEffect(card.angle)

                }

            }
        }
    }
}

struct CardView: View, Hashable, Identifiable {

    var id = UUID()

    var angle : Angle {
        let angle = Angle(degrees: Double.random(in: 0...30))
        print(angle.degrees)
        return angle
    }
    var body: some View {
        ZStack {
            Rectangle()
                .fill(Color(#colorLiteral(red: 0.7450980544, green: 0.1568627506, blue: 0.07450980693, alpha: 1)))
                .frame(width: 100, height: 100 * 1.618)
                .cornerRadius(16)
                .shadow(color: Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)).opacity(0.1), radius: 1, x: 0, y: 1)
                .shadow(color: Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)).opacity(0.2), radius: 10, x: 0, y: 10)

            VStack {
                Text("Card \(angle.degrees)")
                    .font(.system(size: 10) )
                    .foregroundColor(.white)
                    .bold()
            }
        }
    }
}


struct TextButton: View {
    let action: () -> Void
    let text: String

    var body: some View {
        Button(action: action, label: {
            Text(text)
                .padding(.horizontal, 16)
                .padding(.vertical, 16)
                .foregroundColor(.white)
                .background(Color.blue)
                .cornerRadius(.infinity)
                .shadow(color: Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)).opacity(0.1), radius: 1, x: 0, y: 1)
                .shadow(color: Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)).opacity(0.2), radius: 10, x: 0, y: 10)
        })
    }
}
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}



来源:https://stackoverflow.com/questions/61895745/in-swiftui-is-it-possible-to-add-a-new-view-onto-the-screen-with-a-button

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!