繁体   English   中英

在 swiftUI 中的视图数组之间切换

[英]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()
    }
}

顺便说一句,我改变了你的随机逻辑,不确定它是如何工作的,但我认为它对你的问题并不重要。

我建议您删除oneDotDicetwoDotDice ,以获得可以代表所有可能值的单个DiceFace 此外,不需要自定义修饰符,不需要View数组(顺便说一下,如果你想要类似的东西,你可以使用AnyViewForEach )。

您可以将以下示例复制粘贴到 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM