如何在AppKit上以自定义SwiftUI形式右对齐项目标签?

问题描述 投票:1回答:1

我有以下可可形式:

struct Canvas: PreviewProvider {
  static var previews: some View {
    VStack {
      HStack(alignment: .firstTextBaseline) {
        Text("Endpoint:")
        TextField("https://localhost:8080/api", text: .constant(""))
      }
      Divider()
      HStack(alignment: .firstTextBaseline) {
        Text("Path:")
        TextField("/todos", text: .constant(""))
      }
      Spacer()
    }
    .padding()
    .previewLayout(.fixed(width: 280, height: 200))
  }
}

此面板看起来不错,但我想右对齐“端点:”和“路径:”标签:

所以我应用了自定义的水平对齐方式:

struct Canvas: PreviewProvider {
  static var previews: some View {
    VStack(alignment: .label) {
      HStack(alignment: .firstTextBaseline) {
        Text("Endpoint:").alignmentGuide(.label) { $0[.trailing] }
        TextField("https://localhost:8080/api", text: .constant(""))
      }
      Divider()
      HStack(alignment: .firstTextBaseline) {
        Text("Path:").alignmentGuide(.label) { $0[.trailing] }
        TextField("/todos", text: .constant(""))
      }
      Spacer()
    }
    .padding()
    .previewLayout(.fixed(width: 280, height: 200))
  }
}

extension HorizontalAlignment {
  private enum Label: AlignmentID {
    static func defaultValue(in context: ViewDimensions) -> CGFloat {
      context[.leading]
    }
  }
  static let label: HorizontalAlignment = .init(Label.self)
}

结果不是我需要的:

没有文档,请帮助。

forms macos cocoa swiftui appkit
1个回答
0
投票
我不认为对齐指南在当前的实施中会在这里起作用。在和他们玩了一会之后,似乎他们根据容器的给定大小

然后再>>根据指南对齐每个孩子的大小。这导致您看到的怪异行为。下面,我展示了3种不同的技术,这些技术将使您能够以复杂的顺序获得所需的结果。每个人都有其特定示例之外的应用程序。

对于较长的表格,最后一个(label3())将是最可靠的。

struct ContentView: View { @State var sizes: [String:CGSize] = [:] var body: some View { VStack { HStack(alignment: .firstTextBaseline) { self.label3("Endpoint:") TextField("https://localhost:8080/api", text: .constant("")) } Divider() HStack(alignment: .firstTextBaseline) { self.label3("Path:") TextField("/todos", text: .constant("")) } } .padding() .onPreferenceChange(SizePreferenceKey.self) { preferences in self.sizes = preferences } } func label1(_ text: String) -> some View { Text(text) // Use a minimum size based on your best guess. Look around and you'll see that many macOS apps actually lay forms out like this because it's simple to implement. .frame(minWidth: 100, alignment: .trailing) } func label2(_ text: String, sizer: String = "Endpoint:") -> some View { ZStack(alignment: .trailing) { // Use dummy content for sizing based on the largest expected item. This can be great when laying out icons and you know ahead of time which will be the biggest. Text(sizer).opacity(0.0) Text(text) } } func label3(_ text: String) -> some View { Text(text) // Use preferences and save the size of each label .background( GeometryReader { proxy in Color.clear .preference(key: SizePreferenceKey.self, value: [text : proxy.size]) } ) .frame(minWidth: self.sizes.values.map { $0.width }.max() ?? 0.0, alignment: .trailing) } } struct SizePreferenceKey: PreferenceKey { typealias Value = [String:CGSize] static var defaultValue: Value = [:] static func reduce(value: inout Value, nextValue: () -> Value) { let next = nextValue() for (k, v) in next { value[k] = v } } }

这里是label2label3的结果的屏幕截图。The two labels are aligned
© www.soinside.com 2019 - 2024. All rights reserved.