简体   繁体   English

如何向 SwiftUI 视图添加操作?

[英]How do I add an action to a SwiftUI view?

Because I want to use SwiftUI while simultaneously supporting earlier iOS versions, I've had to find a different grid system.因为我想在支持早期 iOS 版本的同时使用 SwiftUI,所以我不得不寻找不同的网格系统。 I have a simple design working, but I can't figure out how to do something with these views of mine.我有一个简单的设计工作,但我不知道如何用我的这些观点做一些事情。 I've tried showing alerts, adding tap gestures, nothing works.我试过显示警报,添加点击手势,没有任何效果。 Am I just making it out harder than it needs to be?我只是让它变得比需要的更难吗?

Here's an image of my interface, which is working fine, I just can't make these views to anything!这是我的界面图像,它工作正常,我无法将这些视图用于任何东西! 在此处输入图像描述

I based my code off of this github repository: https://github.com/pietropizzi/GridStack/blob/master/Sources/GridStack/GridStack.swift我的代码基于这个 github 存储库: https ://github.com/pietropizzi/GridStack/blob/master/Sources/GridStack/GridStack.swift

struct ContentView : View {
  let colors: [Color] = [.red, .green, .blue, .yellow, .purple]
  
  @State private var orientation = UIDeviceOrientation.unknown
  @State private var showAlert = false
  @State private var selectedShortcut: Int = 0 {
    didSet {
      showingHUD = false
    }
  }
  @State private var showingHUD = true
  
  var rows: CGFloat { return orientation.isPortrait || orientation == .unknown ? 5 : 3}
  var columns: CGFloat { return orientation.isPortrait || orientation == .unknown ? 3 : 5 }
  
  var body: some View {
    GeometryReader { proxy in
      GridStack(minCellWidth: (proxy.size.width / (columns + 1)), spacing: 6, numItems: 15) { index, cellWidth in
        CardView(iconName: "star.fill", title: "\(index + 1)", description: "(# \(index + 1))", width: cellWidth, height: (proxy.size.height / (rows)) - 7)
          .background(colors.randomElement())
          .cornerRadius(10)
          .onTapGesture {
            selectedShortcut = index
            showingHUD.toggle()
          }
      }
      if showingHUD {
        HUD {
          Label("Shortcut: \(selectedShortcut)", systemImage: "star.fill")
        }
        .transition(AnyTransition.move(edge: .top).combined(with: .opacity))
        .onAppear {
          DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
            withAnimation {
              showingHUD = false
            }
          }
        }
        .zIndex(1)
      }
    }.background(Color.rgba(red: 40, green: 40, blue: 40, alpha: 1))
      .statusBar(hidden: true)
  }
}

struct HUD<Content: View>: View {
  @ViewBuilder let content: Content
  
  var body: some View {
    content
      .padding(.horizontal, 12)
      .padding(16)
      .background(
        Capsule()
          .foregroundColor(Color.white)
          .shadow(color: Color(.black).opacity(0.16), radius: 12, x: 0, y: 5)
      )
  }
}



struct CardView: View {
  var iconName: String
  var title: String
  var description: String
  var width: CGFloat
  var height: CGFloat
  
  var body: some View {
    VStack(alignment: .center, spacing: 4) {
      Image(systemName: iconName)
        .font(.system(size: 24))
        .padding(.top)
      VStack(alignment: .leading, spacing: 2) {
        Text(description)
          .lineLimit(2)
          .multilineTextAlignment(.leading)
      }
      .padding()
    }.foregroundColor(.white)
      .shadow(color: .darkGray, radius: 2, x: 2, y: 2)
      .frame(minWidth: width, maxWidth: width, minHeight: height, maxHeight: height)
    //      .onTapGesture {
    //        Alert(title: Text("Alert Title"), message: Text("Message"))
    //      }
  }
}

Here's how i usually do it:这是我通常的做法:

Add a callback to your CardView向您的CardView添加回调

struct CardView: View {
    var iconName: String
    var title: String
    var description: String
    var width: CGFloat
    var height: CGFloat
    var action: () -> Void
    
    var body: some View {
        Button {
            self.action()
        } label: {
            VStack(alignment: .center, spacing: 4) {
                Image(systemName: iconName)
                    .font(.system(size: 24))
                    .padding(.top)
                VStack(alignment: .leading, spacing: 2) {
                    Text(description)
                        .lineLimit(2)
                        .multilineTextAlignment(.leading)
                }
                .padding()
            }.foregroundColor(.white)
                .shadow(color: .darkGray, radius: 2, x: 2, y: 2)
                .frame(minWidth: width, maxWidth: width, minHeight: height, maxHeight: height)
        }
    }
}

And then you use your CardView like this:然后你像这样使用你的 CardView:

CardView(iconName: "star.fill", title: "\(index + 1)", description: "(# \(index + 1))", width: cellWidth, height: (proxy.size.height / (rows)) - 7, action: {
    selectedShortcut = index
    showingHUD.toggle()
    
})
.background(colors.randomElement())
.cornerRadius(10)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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