【问题标题】:Align two SwiftUI text views in HStack with correct alignment正确对齐 HStack 中的两个 SwiftUI 文本视图
【发布时间】:2019-10-28 12:15:01
【问题描述】:

我有一个包含两行的简单列表视图。

每行包含两个文本视图。查看一和查看二。

我想对齐每行中的最后一个标签(查看两个),以便名称标签前导对齐,并且无论字体大小如何都保持对齐。

第一个标签(查看一个)也需要前导对齐。

我尝试在第一个标签(查看一个)上设置最小帧宽度,但它不起作用。设置最小宽度并让文本视图在视图一中对齐似乎也是不可能的。

有什么想法吗?这在 UIKit 中是相当直接的。

【问题讨论】:

    标签: ios swiftui


    【解决方案1】:

    我找到了一种解决此问题的方法,该方法支持动态类型并且不是 hacky。答案是使用PreferenceKeysGeometryReader

    这个解决方案的本质是每个数字Text 都会有一个宽度,根据它的文本大小绘制它。 GeometryReader 可以检测到这个宽度,然后我们可以使用 PreferenceKey 将其冒泡到 List 本身,在那里可以跟踪最大宽度,然后分配给每个数字 Text 的帧宽度。

    PreferenceKey 是您使用关联类型创建的类型(可以是符合 Equatable 的任何结构,这是您存储有关首选项的数据的地方),它附加到任何 View,并且当它是附加后,它会在视图树中冒泡,并且可以使用 .onPreferenceChange(PreferenceKeyType.self) 在祖先视图中收听。

    首先,我们将创建 PreferenceKey 类型及其包含的数据:

    struct CenteringColumnPreferenceKey: PreferenceKey {
        typealias Value = [CenteringColumnPreference]
    
        static var defaultValue: [CenteringColumnPreference] = []
    
        static func reduce(value: inout [CenteringColumnPreference], nextValue: () -> [CenteringColumnPreference]) {
            value.append(contentsOf: nextValue())
        }
    }
    
    struct CenteringColumnPreference: Equatable {
        let width: CGFloat
    }
    

    接下来,我们将创建一个名为CenteringView 的视图,它将附加到我们想要调整大小的任何内容(在本例中为数字标签)的背景。这将负责设置首选项,该首选项将使用 PreferenceKeys 传递此数字标签的首选宽度。

    struct CenteringView: View {
        var body: some View {
            GeometryReader { geometry in
                Rectangle()
                    .fill(Color.clear)
                    .preference(
                        key: CenteringColumnPreferenceKey.self,
                        value: [CenteringColumnPreference(width: geometry.frame(in: CoordinateSpace.global).width)]
                    )
            }
        }
    }
    

    最后,列表本身!我们有一个@State 变量,它是数字“列”的宽度(不是真正的列,因为数字不会直接影响代码中的其他数字)。通过.onPreferenceChange(CenteringColumnPreference.self),我们监听我们创建的首选项的变化并将最大宽度存储在我们的宽度状态中。在绘制完所有数字标签并由 GeometryReader 读取它们的宽度后,宽度会向上传播,并且最大宽度由 .frame(width: width) 分配。

    struct ContentView: View {
        @State private var width: CGFloat? = nil
    
        var body: some View {
            List {
                HStack {
                    Text("1. ")
                        .frame(width: width, alignment: .leading)
                        .lineLimit(1)
                        .background(CenteringView())
                    Text("John Smith")
                }
                HStack {
                    Text("20. ")
                        .frame(width: width, alignment: .leading)
                        .lineLimit(1)
                        .background(CenteringView())
                    Text("Jane Done")
                }
                HStack {
                    Text("2000. ")
                        .frame(width: width, alignment: .leading)
                        .lineLimit(1)
                        .background(CenteringView())
                    Text("Jax Dax")
                }
            }.onPreferenceChange(CenteringColumnPreferenceKey.self) { preferences in
                for p in preferences {
                    let oldWidth = self.width ?? CGFloat.zero
                    if p.width > oldWidth {
                        self.width = p.width
                    }
                }
            }
        }
    }
    

    如果您有多列数据,一种扩展方法是对列进行枚举或对它们进行索引,宽度的@State 将成为字典,其中每个键都是一列,.onPreferenceChange 进行比较针对列的最大宽度的键值。

    为了显示结果,this 是打开较大文本后的样子,就像一个魅力:)。

    这篇关于 PreferenceKey 和检查视图树的文章非常有帮助:https://swiftui-lab.com/communicating-with-the-view-tree-part-1/

    【讨论】:

      【解决方案2】:

      我只需要处理这个。依赖固定宽度frame 的解决方案不适用于动态类型,因此我无法使用它们。我解决它的方法是将灵活的项目(在本例中为左侧数字)放入带有包含最宽允许内容的占位符的 ZStack,然后将占位符的不透明度设置为 0:

      ZStack {
          Text("9999")
              .opacity(0)
              .accessibility(visibility: .hidden)
          Text(id)
      }
      

      它很hacky,但至少它支持动态类型?‍♂️

      下面的完整示例! ?

      import SwiftUI
      
      struct Person: Identifiable {
          var name: String
          var id: Int
      }
      
      struct IDBadge : View {
          var id: Int
          var body: some View {
              ZStack(alignment: .trailing) {
                  Text("9999.") // The maximum width dummy value
                      .font(.headline)
                      .opacity(0)
                      .accessibility(visibility: .hidden)
                  Text(String(id) + ".")
                      .font(.headline)
              }
          }
      }
      
      struct ContentView : View {
          var people: [Person]
          var body: some View {
              List(people) { person in
                  HStack(alignment: .top) {
                      IDBadge(id: person.id)
                      Text(person.name)
                          .lineLimit(nil)
                  }
              }
          }
      }
      
      #if DEBUG
      struct ContentView_Previews : PreviewProvider {
          static let people = [Person(name: "John Doe", id: 1), Person(name: "Alexander Jones", id: 2000), Person(name: "Tom Lee", id: 45)]
          static var previews: some View {
              Group {
                  ContentView(people: people)
                      .previewLayout(.fixed(width: 320.0, height: 150.0))
                  ContentView(people: people)
                      .environment(\.sizeCategory, .accessibilityMedium)
                      .previewLayout(.fixed(width: 320.0, height: 200.0))
              }
          }
      }
      #endif
      

      【讨论】:

      • 这似乎很有趣@mbxDev - 必须看看这个。不错。
      • 让我知道这是否适合您@Edward!我在我当前的应用程序中一直在使用它。
      • 嗨 - 谢谢!但是由于某些奇怪的原因,当我有两个 Text 元素时,.trailing 出现错误,就像你的例子一样;但如果我只有一个 Text 元素,我没有。错误是“静态成员'尾随'不能用于'Alignment'类型的实例”。奇怪的是Text元素的数量导致了这个?你有什么想法吗?
      • 我想通了。 Swift 的编译器太让人抓狂了。该行应为.accessibility(hidden: true)
      • 通常我不喜欢这样的黑客,但它的简单性使它实际上非常优雅?
      【解决方案3】:

      在 Swift 5.2 和 iOS 13 中,您可以使用PreferenceKey 协议、preference(key:value:) 方法和onPreferenceChange(_:perform:) 方法来解决这个问题。

      您可以通过3个主要步骤实现OP提出的View的代码,如下所示。


      #1。初步实施

      import SwiftUI
      
      struct ContentView: View {
      
          var body: some View {
              NavigationView {
                  List {
                      HStack {
                          Text("5.")
                          Text("John Smith")
                      }
                      HStack {
                          Text("20.")
                          Text("Jane Doe")
                      }
                  }
                  .listStyle(GroupedListStyle())
                  .navigationBarTitle("Challenge")
              }
          }
      
      }
      

      #2。中间实现(设置等宽)

      这里的想法是收集代表等级的Texts 的所有宽度,并将其中最宽的宽度分配给ContentViewwidth 属性。

      import SwiftUI
      
      struct WidthPreferenceKey: PreferenceKey {
      
          static var defaultValue: [CGFloat] = []
          static func reduce(value: inout [CGFloat], nextValue: () -> [CGFloat]) {
              value.append(contentsOf: nextValue())
          }
      
      }
      
      struct ContentView: View {
      
          @State private var width: CGFloat? = nil
      
          var body: some View {
              NavigationView {
                  List {
                      HStack {
                          Text("5.")
                              .overlay(
                                  GeometryReader { proxy in
                                      Color.clear
                                          .preference(
                                              key: WidthPreferenceKey.self,
                                              value: [proxy.size.width]
                                          )
                                  }
                              )
                              .frame(width: width, alignment: .leading)
                          Text("John Smith")
                      }
                      HStack {
                          Text("20.")
                              .overlay(
                                  GeometryReader { proxy in
                                      Color.clear
                                          .preference(
                                              key: WidthPreferenceKey.self,
                                              value: [proxy.size.width]
                                          )
                                  }
                              )
                              .frame(width: width, alignment: .leading)
                          Text("Jane Doe")
                      }
                  }
                  .onPreferenceChange(WidthPreferenceKey.self) { widths in
                      if let width = widths.max() {
                          self.width = width
                      }
                  }
                  .listStyle(GroupedListStyle())
                  .navigationBarTitle("Challenge")
              }
          }
      
      }
      

      #3。最终实现(重构)

      为了使我们的代码可重用,我们可以将 preference 逻辑重构为 ViewModifier

      import SwiftUI
      
      struct WidthPreferenceKey: PreferenceKey {
      
          static var defaultValue: [CGFloat] = []
          static func reduce(value: inout [CGFloat], nextValue: () -> [CGFloat]) {
              value.append(contentsOf: nextValue())
          }
      
      }
      
      struct EqualWidth: ViewModifier {
      
          func body(content: Content) -> some View {
              content
                  .overlay(
                      GeometryReader { proxy in
                          Color.clear
                              .preference(
                                  key: WidthPreferenceKey.self,
                                  value: [proxy.size.width]
                              )
                      }
                  )
          }
      
      }
      
      extension View {
          func equalWidth() -> some View {
              modifier(EqualWidth())
          }
      }
      
      struct ContentView: View {
      
          @State private var width: CGFloat? = nil
      
          var body: some View {
              NavigationView {
                  List {
                      HStack {
                          Text("5.")
                              .equalWidth()
                              .frame(width: width, alignment: .leading)
                          Text("John Smith")
                      }
                      HStack {
                          Text("20.")
                              .equalWidth()
                              .frame(width: width, alignment: .leading)
                          Text("Jane Doe")
                      }
                  }
                  .onPreferenceChange(WidthPreferenceKey.self) { widths in
                      if let width = widths.max() {
                          self.width = width
                      }
                  }
                  .listStyle(GroupedListStyle())
                  .navigationBarTitle("Challenge")
              }
          }
      
      }
      

      结果如下:

      【讨论】:

        【解决方案4】:

        这里有三个静态选项。

        struct ContentView: View {
            @State private var width: CGFloat? = 100
        
            var body: some View {
                List {
                    HStack {
                        Text("1. ")
                            .frame(width: width, alignment: .leading)
                            .lineLimit(1)
                            .background(Color.blue)
                        // Option 1
                        Text("John Smith")
                            .multilineTextAlignment(.leading)
                            //.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
                            .background(Color.green)
                    }
                    HStack {
                        Text("20. ")
                            .frame(width: width, alignment: .leading)
                            .lineLimit(1)
                            .background(Color.blue)
                        // Option 2 (works mostly like option 1)
                        Text("Jane Done")
                            .background(Color.green)
                        Spacer()
                    }
                    HStack {
                        Text("2000. ")
                            .frame(width: width, alignment: .leading)
                            .lineLimit(1)
                            .background(Color.blue)
                        // Option 3 - takes all the rest space to the right
                        Text("Jax Dax")
                            .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
                            .background(Color.green)
                    }
                }
            }
        }
        

        它的外观如下:

        我们可以根据this answer 中建议的最长条目来计算宽度。

        有几个选项可以动态计算宽度。

        选项 1

        import SwiftUI
        import Combine
        
        struct WidthGetter: View {
            let widthChanged: PassthroughSubject<CGFloat, Never>
            var body: some View {
                GeometryReader { (g) -> Path in
                    print("width: \(g.size.width), height: \(g.size.height)")
                    self.widthChanged.send(g.frame(in: .global).width)
                    return Path() // could be some other dummy view
                }
            }
        }
        
        struct ContentView: View {
            let event = PassthroughSubject<CGFloat, Never>()
        
            @State private var width: CGFloat?
        
            var body: some View {
                List {
                    HStack {
                        Text("1. ")
                            .frame(width: width, alignment: .leading)
                            .lineLimit(1)
                            .background(Color.blue)
                            .background(WidthGetter(widthChanged: event))
         
                        // Option 1
                        Text("John Smith")
                            .multilineTextAlignment(.leading)
                            //.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
                            .background(Color.green)
                    }
                    HStack {
                        Text("20. ")
                            .frame(width: width, alignment: .leading)
                            .lineLimit(1)
                            .background(Color.blue)
                            .background(WidthGetter(widthChanged: event))
                        // Option 2 (works mostly like option 1)
                        Text("Jane Done")
                            .background(Color.green)
                        Spacer()
                    }
                    HStack {
                        Text("2000. ")
                            .frame(width: width, alignment: .leading)
                            .lineLimit(1)
                            .background(Color.blue)
                            .background(WidthGetter(widthChanged: event))
                        // Option 3 - takes all the rest space to the right
                        Text("Jax Dax")
                            .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
                            .background(Color.green)
                    }
                }.onReceive(event) { (w) in
                    print("event ", w)
                    if w > (self.width ?? .zero) {
                        self.width = w
                    }
                }
            }
        }
        

        选项 2

        import SwiftUI
        
        struct ContentView: View {
            
            @State private var width: CGFloat?
            
            var body: some View {
                List {
                    HStack {
                        Text("1. ")
                            .frame(width: width, alignment: .leading)
                            .lineLimit(1)
                            .background(Color.blue)
                            .alignmentGuide(.leading, computeValue: { dimension in
                                self.width = max(self.width ?? 0, dimension.width)
                                return dimension[.leading]
                            })
                        
                        // Option 1
                        Text("John Smith")
                            .multilineTextAlignment(.leading)
                            //.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
                            .background(Color.green)
                    }
                    HStack {
                        Text("20. ")
                            .frame(width: width, alignment: .leading)
                            .lineLimit(1)
                            .background(Color.blue)
                            .alignmentGuide(.leading, computeValue: { dimension in
                                self.width = max(self.width ?? 0, dimension.width)
                                return dimension[.leading]
                            })
                        // Option 2 (works mostly like option 1)
                        Text("Jane Done")
                            .background(Color.green)
                        Spacer()
                    }
                    HStack {
                        Text("2000. ")
                            .frame(width: width, alignment: .leading)
                            .lineLimit(1)
                            .background(Color.blue)
                            .alignmentGuide(.leading, computeValue: { dimension in
                                self.width = max(self.width ?? 0, dimension.width)
                                return dimension[.leading]
                            })
                        // Option 3 - takes all the rest space to the right
                        Text("Jax Dax")
                            .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
                            .background(Color.green)
                    }
                }
            }
        }
        

        结果如下所示:

        【讨论】:

        • 这个答案真的很有帮助......我将超过 3 个项目与.frame(minWidth: 100,idealWidth: 150,maxWidth:.infinity, alignment: .leading) 对齐......这个方法工作得很好......
        【解决方案5】:

        您可以在 HStack 中添加两个 Texts,然后是 SpacerSpacer 会将您的 Texts 推向左侧,如果 Texts 由于内容长度而改变大小,所有内容都会自行调整:

        HStack {
            Text("1.")
            Text("John Doe")
            Spacer()
        }
        .padding()
        

        Texts 在技术上是居中对齐的,但是由于视图会自动调整大小并且只占用与其中的文本一样多的空间(因为我们没有明确设置框架大小),并且被推送到在Spacer 左边,它们看起来是左对齐的。与设置固定宽度相比,这样做的好处是您不必担心文本会被截断。

        另外,我在HStack 中添加了填充以使其看起来更漂亮,但如果您想调整Texts 彼此之间的接近程度,您可以手动设置其任一侧的填充。 (您甚至可以设置负填充以将项目彼此推得比它们的自然间距更近)。

        编辑

        没有意识到 OP 也需要第二个 Text 垂直对齐。我有办法做到这一点,但它“hacky”并且如果没有更多的工作就无法用于更大的字体:

        这些是数据对象:

        class Person {
            var name: String
            var id: Int
            init(name: String, id: Int) {
                self.name = name
                self.id = id
            }
        }
        
        class People {
            var people: [Person]
            init(people: [Person]) {
                self.people = people
            }
            func maxIDDigits() -> Int {
                let maxPerson = people.max { (p1, p2) -> Bool in
                    p1.id < p2.id
                }
                print(maxPerson!.id)
                let digits = log10(Float(maxPerson!.id)) + 1
                return Int(digits)
            }
            func minTextWidth(fontSize: Int) -> Length {
                print(maxIDDigits())
                print(maxIDDigits() * 30)
                return Length(maxIDDigits() * fontSize)
            }
        }
        

        这是View

        var people = People(people: [Person(name: "John Doe", id: 1), Person(name: "Alexander Jones", id: 2000), Person(name: "Tom Lee", id: 45)])
        var body: some View {   
            List {
                ForEach(people.people.identified(by: \.id)) { person in                
                    HStack {
                        Text("\(person.id).")
                            .frame(minWidth: self.people.minTextWidth(fontSize: 12), alignment: .leading)
                        Text("\(person.name)")
        
                    }
                }
            }
        }
        

        要使其适用于多种字体大小,您必须获取字体大小并将其传递给minTextWidth(fontSize:)

        再次,我想强调这是“hacky”并且可能违反 SwiftUI 原则,但我找不到内置方法来执行您要求的布局(可能是因为 Texts 在不同行不相互交互,因此它们无法知道如何保持垂直对齐)。

        编辑 2 上面的代码生成这个:

        【讨论】:

        • 这没有回答问题,但感谢您的建议
        • @Edward 那么我对你的问题感到困惑。您不希望文本在视图中处于领先地位吗?这与那个结果相同。自己测试一下。
        • 查看我的问题中的图片。它涉及多行。基本上,您在 HStack 中有两个标签 - 如何确保第二个标签在列表中对齐,同时保持两个标签在一行(单元格)中前导对齐?
        • @Edward 编辑了我的答案,因为我更好地理解了你的问题。
        • 太棒了!感谢您的回答,我认为“hacky”方式是目前唯一的方式。
        【解决方案6】:

        您可以将固定宽度设置为数字Text 视图。它使这个Text 组件具有固定大小。

        HStack {
                Text(item.number)
                    .multilineTextAlignment(.leading)
                    .frame(width: 30)
                Text(item.name)
        }
        

        这种解决方案的缺点是,如果那里有较长的文本,它将被换行并以“...”结尾,但在这种情况下,我认为您可以粗略估计哪个宽度就足够了。

        【讨论】:

        • 嘿@kamwysoc 这种方法的问题是第一个标签文本实际上并没有领先。它似乎被框架修饰符覆盖。此外,我认为这不适用于较大的文本大小。
        【解决方案7】:

        如果您可以接受 1 行限制:

        Group {
            HStack {
                VStack(alignment: .trailing) {
                    Text("Vehicle:")
                    Text("Lot:")
                    Text("Zone:")
                    Text("Location:")
                    Text("Price:")
                }
                VStack(alignment: .leading) {
                    Text("vehicle")
                    Text("lot")
                    Text("zone")
                    Text("location")
                    Text("price")
                }
            }
            .lineLimit(1)
            .font(.footnote)
            .foregroundColor(.secondary)
        }
        .frame(maxWidth: .infinity)
        

        【讨论】:

          【解决方案8】:

          Xcode 12.5

          如果您知道要偏移第二个视图的量,则可以将两个视图放在前导对齐的 ZStack 中,并在第二个视图上使用 .padding(.horizontal, amount) 修饰符来偏移它。

          var body: some View {
              NavigationView {
                  List {
                      ForEach(persons) { person in
                          ZStack(alignment: .leading) {
                              Text(person.number)
                              Text(person.name)
                                  .padding(.horizontal, 30)
                          }
                      }
                  }
                  .navigationTitle("Challenge")
              }
          }
          

          【讨论】:

            【解决方案9】:
            HStack {
                        HStack {
                            Spacer()
                            Text("5.")
                        }
                        .frame(width: 40)
            
                        Text("Jon Smith")
                    }
            

            但这仅适用于固定宽度。 .frame(minWidth: 40) 将填满整个 View 因为 Space()

            .multilineTextAlignment(.leading) 在我的测试中没有任何影响。

            【讨论】:

              【解决方案10】:

              在尝试让它工作一整天后,我想出了这个解决方案:

              编辑:Link to Swift Package

              import SwiftUI
              
              fileprivate extension Color {
                  func exec(block: @escaping ()->Void) -> Self {
                      block()
                      return self
                  }
              }
              
              fileprivate class Deiniter {
                  let block: ()->Void
                  init(block: @escaping ()->Void) {
                      self.block = block
                  }
                  deinit {
                     block()
                  }
              }
              struct SameWidthContainer<Content: View>: View {
                  private var id: UUID
                  private let deiniter: Deiniter
                  @ObservedObject private var group: WidthGroup
                  private var content: () -> Content
                  
                  init(group: WidthGroup, content: @escaping ()-> Content) {
                      self.group = group
                      self.content = content
                      
                      let id = UUID()
                      self.id = id
                      
              
                      WidthGroup.widths[group.id]?[id] = 100.0
                      self.deiniter = Deiniter() {
                          WidthGroup.widths[group.id]?.removeValue(forKey: id)
                      }
                  }
                  
                  
                  var body: some View {
                      ZStack(alignment: .leading) {
                          Rectangle()
                              .frame(width: self.group.width, height: 1)
                              .foregroundColor(.clear)
                          
                          content()
                              .overlay(
                                  GeometryReader { proxy in
                                      Color.clear
                                          .exec {
                                              WidthGroup.widths[self.group.id]?[self.id] = proxy.size.width
                                              let newWidth = WidthGroup.widths[group.id]?.values.max() ?? 0
                                              if newWidth != self.group.width {
                                                  self.group.width = newWidth
                                              }
                                          }
                                  }
                              )
                      }
                  }
              }
              
              class WidthGroup: ObservableObject {
              
                  static var widths: [UUID: [UUID: CGFloat]] = [:]
                  @Published var width: CGFloat = 0.0
                  
                  let id: UUID
                  
                  init() {
                      let id = UUID()
                      self.id = id
                      
                      WidthGroup.widths[id] = [:]
                  }
                  
                  deinit {
                      WidthGroup.widths.removeValue(forKey: id)
                  }
              }
              
              struct SameWidthText_Previews: PreviewProvider {
                  
                  private static let GROUP = WidthGroup()
                  
                  static var previews: some View {
                      Group {
                          SameWidthContainer(group: Self.GROUP) {
                              Text("One")
                          }
                              
                          SameWidthContainer(group: Self.GROUP) {
                              Text("Two")
                          }
                          SameWidthContainer(group: Self.GROUP)  {
                              Text("Three")
                          }
                      }
                  }
              }
              

              然后这样使用:

              struct SomeView: View {
                  
                  @State private var group1 = WidthGroup()
                  @State private var group2 = WidthGroup()
                  
                  var body: some View {
                      VStack() {
                          ForEach(9..<12) { index in
                              HStack {
                                  SameWidthContainer(group: group1) {
                                      Text("All these will have same width in group 1 \(index)")
                                  }
                                  
                                  Text("Some other text")
                                  
                                  SameWidthContainer(group: group2) {
                                      Text("All these will have same width in group 2 \(index)")
                                  }
                              }
                          }
                      }
                  }
              }
              

              如果其中一个视图增长或缩小,同一组中的所有视图都将随之增长/缩小。我只是让它工作,所以我没有尝试过那么多。 这有点像黑客,但是,嘿,这似乎不是黑客以外的另一种方式。

              【讨论】:

              • 我为感兴趣的人制作了一个带有示例的快速包here
              【解决方案11】:

              我认为正确的方法是使用HorizontalAlignment。比如:

              extension HorizontalAlignment {
                  private enum LeadingName : AlignmentID {
                      static func defaultValue(in d: ViewDimensions) -> Length { d[.leading] }
                  }
                  static let leadingName = HorizontalAlignment(LeadingName.self)
              }
              
              List (people.identified(by: \.id)) {person in
                  HStack {
                      Text("\(person.id)")
                      Text("\(person.name)").alignmentGuide(.leadingName) {d in d[.leading]}
                  }
              }
              

              但我无法让它工作。

              我在列表中找不到任何此类示例。似乎 List 不支持对齐(还没有?)

              我可以让它与 VStack 和硬编码值一起工作,例如:

                      VStack (alignment: .leadingName ) {
                      HStack {
                          Text("1.")
                          Text("John Doe").alignmentGuide(.leadingName) {d in d[.leading]}
                          Spacer()
                      }
                      HStack {
                          Text("2000.")
                          Text("Alexander Jones").alignmentGuide(.leadingName) {d in d[.leading]}
                          Spacer()
                      }
                      HStack {
                          Text("45.")
                          Text("Tom Lee").alignmentGuide(.leadingName) {d in d[.leading]}
                          Spacer()
                      }
                  }
              

              我希望这将在以后的测试版中得到修复...

              【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2020-06-11
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-07-05
              • 2020-03-19
              相关资源
              最近更新 更多