在 swiftUI 中是否可以使用按钮在屏幕上添加新视图?
In swiftUI is it possible to add a new view onto the screen with a button?
每次点击按钮时,我都希望出现一个新的 cardView。我想知道这在 swiftUI 中是否可行,如果可行,我需要采取什么行动。如果我能够将一些参数传递给 cardView 结构,那就更好了,但任何帮助都会很棒!
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()
}
} ```
看看这个:
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()
}
}
在SwiftUI中,View反映的是State数据,所以不是直接修改View,而是修改State数据,根据State构建View。这是 SwiftUI 背后的核心原则,它允许您将视图关注点与驱动它的数据(某些行话中的 ViewModel)分开。
所以,假设我们有一个 Card
的数据模型(使其符合 Identifiable
- 稍后需要):
struct Card: Identifiable {
let id = UUID()
let name: String
}
让我们在视图中定义一个卡片数组作为状态变量:
@State private var cards: [Card] = [Card(name: "foo")]
然后主体可以用 ForEach
或 List
视图显示这些卡片:
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
}
}
}
按钮的闭包会向 cards
状态变量添加一个新的 Card
实例。而已。它不会直接更改视图中的任何内容。 View 看到变化(这是 SwiftUI 在幕后所做的)并重新呈现自己。
你需要 Card
来符合 Identifiable
的原因是让 ForEach
知道如何唯一地识别每张卡。在不符合可识别的情况下,您可以使用这样的关键路径:
ForEach(cards, id: \.self) { card in
// ...
}
每次点击按钮时,我都希望出现一个新的 cardView。我想知道这在 swiftUI 中是否可行,如果可行,我需要采取什么行动。如果我能够将一些参数传递给 cardView 结构,那就更好了,但任何帮助都会很棒!
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()
}
} ```
看看这个:
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()
}
}
在SwiftUI中,View反映的是State数据,所以不是直接修改View,而是修改State数据,根据State构建View。这是 SwiftUI 背后的核心原则,它允许您将视图关注点与驱动它的数据(某些行话中的 ViewModel)分开。
所以,假设我们有一个 Card
的数据模型(使其符合 Identifiable
- 稍后需要):
struct Card: Identifiable {
let id = UUID()
let name: String
}
让我们在视图中定义一个卡片数组作为状态变量:
@State private var cards: [Card] = [Card(name: "foo")]
然后主体可以用 ForEach
或 List
视图显示这些卡片:
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
}
}
}
按钮的闭包会向 cards
状态变量添加一个新的 Card
实例。而已。它不会直接更改视图中的任何内容。 View 看到变化(这是 SwiftUI 在幕后所做的)并重新呈现自己。
你需要 Card
来符合 Identifiable
的原因是让 ForEach
知道如何唯一地识别每张卡。在不符合可识别的情况下,您可以使用这样的关键路径:
ForEach(cards, id: \.self) { card in
// ...
}