[英]Switching between an array of views in swiftUI
Swift 5.x iOS 13.x
我有一组我创建的骰子视图,我想在它们之间切换。 我在这里只展示两个视图以保持简短。 我创建了一组视图,但我不知道如何在 SwiftUI 中解决它? 或者实际上是什么类型的 object 视图,因为它不是视图或某些视图。
import SwiftUI
import GameplayKit
let dotSize:CGFloat = 24
let diceSize:CGFloat = 128
let fieldSide:CGFloat = 32
let d6 = GKRandomDistribution.d2()
var diceViews:[Any] = [oneDotDice(),twoDotDice()]
struct ContentView: View {
@State var showInt:Int = 1
var body: some View {
VStack {
if showInt == 1 {
oneDotDice()
.transition(AnyTransition.opacity)
.animation(.default)
.modifier(changeDice(showInt: self.$showInt))
}
if showInt == 2 {
twoDotDice()
.transition(AnyTransition.opacity)
.animation(.default)
.modifier(changeDice(showInt: self.$showInt))
}
}
}
struct oneDotDice: View {
var body: some View {
Rectangle()
.fill(Color.clear)
.frame(width: diceSize, height: diceSize, alignment: .center)
.border(Color.black)
.background(Text(1))
}
}
struct twoDotDice: View {
var body: some View {
Rectangle()
.fill(Color.clear)
.frame(width: diceSize, height: diceSize, alignment: .center)
.border(Color.black)
.background(Text(2))
}
}
struct changeDice: ViewModifier {
@Binding var showInt:Int
func body(content: Content) -> some View {
content
.onTapGesture {
self.showInt = d6.nextInt()
print("Int ",self.showInt)
}
}
}
如何在主循环中使用我的视图数组更好地编写此代码? 我什至不能使用 SwiftUI 代码中的 switch 语句。 我需要使用六个嵌套的 if/else 语句......
View 只是一个结构。 您可以将其存储在数组或其他属性类型中,然后在另一个视图中使用它。 如果你真的想在一个集合中混合不同类型的 View, AnyView
是一个很好的解决方案。 为了动态显示该集合,我喜欢使用 ForeEach。 您可以迭代的不是确切的视图,而是数组的索引。 因此 SwiftUI 将从它的数组索引中创建这个视图的键。 但这是有代价的。 您不能动态更改该数组的内容。 它必须在所有父视图生命周期中保持不变。 老实说,您实际上可以通过 ForeEach 迭代确切的视图,但您需要使它们可识别(它们必须具有public var id = UUID()
属性)。
import SwiftUI
let dotSize:CGFloat = 24
let diceSize:CGFloat = 128
let fieldSide:CGFloat = 32
struct ContentView: View {
var diceViews:[AnyView] = [AnyView(oneDotDice()), AnyView(twoDotDice())]
@State var showInt: Int = 1
var body: some View {
ZStack{
ForEach(diceViews.indices){ind in
ZStack{
if ind == self.showInt{
self.diceViews[ind]
.transition(.scale(scale: 0, anchor: .center))
.onTapGesture {
let newShow = Int.random(in: 0...1)
print("new show id \(newShow)")
withAnimation(.linear(duration: 0.3)){
self.showInt = newShow
}
}
}
}
}
}
}
}
struct oneDotDice: View {
var text: String = "1"
var body: some View {
Rectangle()
.fill(Color.clear)
.frame(width: diceSize, height: diceSize)
.border(Color.black)
.background(Text(text))
}
}
struct twoDotDice: View {
var text: String = "2"
var body: some View {
Rectangle()
.fill(Color.clear)
.frame(width: diceSize, height: diceSize)
.border(Color.black)
.background(Text(text))
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
顺便说一句,我改变了你的随机逻辑,不确定它是如何工作的,但我认为它对你的问题并不重要。
我建议您删除oneDotDice
和twoDotDice
,以获得可以代表所有可能值的单个DiceFace
。 此外,不需要自定义修饰符,不需要View
数组(顺便说一下,如果你想要类似的东西,你可以使用AnyView
或ForEach
)。
您可以将以下示例复制粘贴到 Playground 中以进行检查:
import SwiftUI
import GameplayKit
import PlaygroundSupport
let dotSize: CGFloat = 24
let diceSize: CGFloat = 128
let fieldSide: CGFloat = 32
let d6 = GKRandomDistribution(forDieWithSideCount: 6)
struct ContentView: View {
@State var currentValue: Int = 1
var body: some View {
DiceFace(dotCount: currentValue)
.transition(AnyTransition.opacity)
.animation(.default)
.onTapGesture(perform: self.roll)
}
func roll() {
self.currentValue = d6.nextInt()
print("Int: \(self.currentValue)")
}
// Your `oneDotDice` and `twoDotDice` can be represented with this View, passing simply a different `dotCount`
// Also, in Swift types go with an uppercase, and variables with a lowercase.
struct DiceFace: View {
let dotCount: Int
var body: some View {
Rectangle()
.fill(Color.clear)
.frame(width: diceSize, height: diceSize, alignment: .center)
.border(Color.black)
.background(Text(String(dotCount)))
}
}
}
PlaygroundPage.current.setLiveView(ContentView())
PlaygroundPage.current.needsIndefiniteExecution = true
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.