0

我有一个复杂的对齐情况,我希望alignmentGuides 有一些解决方案,但我想不通。

我需要对齐以下条目列表(采用单色字体),使其作为一个组水平居中。

它也以相同的方式定位,并沿前缘以相同的方式对齐,即使一行中的一个条目更长:

我不想硬编码任何大小或定位值。

这是一些要复制的简单代码:

struct TestView: View {

    let values: [(String, String)] = [
        ("03", "30.123"),
        ("02", "33.222"),
        ("01", "completed")
    ]

    var body: some View {
        LazyVStack {
            ForEach(values, id: \.1) { tuple in 
                HStack(spacing: 24) {
                    Text(tuple.0)
                    Text(tuple.1)
                }
            }
        }
        .frame(width: 350, height: 250) // to simulate outer container dimensions
    }
}
4

3 回答 3

1

这是一个简单的方法可能会有所帮助:

struct ContentView: View {
    
    var body: some View {
        
        TestView()

    }
    
}

struct TestView: View {
    
    let values: [(String, String)] = [
        ("03", "30.123"),
        ("02", "33.222"),
        ("01", "completed")
    ]
    
    var body: some View {
        
        HStack(spacing: 24) {
            
            VStack { ForEach(values, id: \.1) { tuple in Text(tuple.0) } }

            VStack(alignment: .leading) { ForEach(values, id: \.1) { tuple in

                Text("00.000")
                    .foregroundColor(Color.clear)
                    .overlay(Text(tuple.1).lineLimit(1).fixedSize(), alignment: .leading)
  
            } }
            
        }
        .font(Font.system(.body, design: .monospaced))
        .padding(5.0)
        .background(Color.pink.opacity(0.5).cornerRadius(5.0))

    }
}

在此处输入图像描述

于 2021-09-26T21:30:36.940 回答
0

我找到解决这个问题的方法,尽管这对我来说似乎很复杂。在这里发帖,但仍然希望有更好的解决方案。

这个想法是使用带有虚拟内容的占位符(依赖于这是一个等宽字体的事实)并使用anchorPreference它来围绕其前沿对齐。

struct LeadingPreferenceKey: PreferenceKey {
   static var defaultValue: Anchor<CGPoint>? = nil
    
   static func reduce(value: inout Anchor<CGPoint>?, 
                      nextValue: () -> Anchor<CGPoint>?) {
      value = nextValue()
   }
}

然后,将其设置为anchorPreference,并将其捕获overlayPreferenceValue并定位offset(x:)

LazyVStack(alignment: .center) {
   row(("00", "00.000")) // placeholder that's center-positioned
      .opacity(0)
      .anchorPreference(key: LeadingPreferenceKey.self,
                        value: .leading, , transform: { $0 })
}
.overlayPreferenceValue(LeadingPreferenceKey.self) { leading in
   GeometryReader { geo in 
      LazyVStack(alignment: .leading) {
         ForEach(values, id: \.1) { tuple in
            row(tuple)
         }
      }
      .offset(x: leading.map { geo[$0].x } ?? 0)
   }
}
func row(_ tuple: (String, String)) -> some View {
   HStack(spacing: 24) {
      Text(tuple.0)
      Text(tuple.1)
   }
}
于 2021-09-26T21:20:13.063 回答
0

这是一个解决方案,它将提供您的对齐以及对列宽的控制。它是一个单独的视图,它接受一个元组并在宽度包含的 HStack 中返回两个 VStack:

struct TwoItemLeadingAlignedColumn: View {
    let firstColumnItems: [String]
    let secondColumnItems: [String]
    let width: CGFloat?
    
    init(items: [(String, String)], width: CGFloat? = nil) {
        firstColumnItems = items.map { $0.0 }
        secondColumnItems = items.map { $0.1 }
        self.width = width
    }
    
    var body: some View {
        GeometryReader { geometry in
            HStack {
                VStack(alignment: .center) {
                    ForEach(firstColumnItems, id: \.self) {item in
                        Text(item)
                    }
                }
                
                Spacer()
                    .frame(width: geometry.size.width * 0.25)
                
                VStack(alignment: .leading) {
                    ForEach(secondColumnItems, id: \.self) {item in
                        Text(item)
                    }
                }
                Spacer()
            }
        .frame(width: width)
        }
    }
}
    

struct TestView: View {
    
    let values: [(String, String)] = [
        ("03", "30.123"),
        ("02", "33.222"),
        ("01", "completed")
    ]
    
    var body: some View {
        TwoItemLeadingAlignedColumn(items: values, width: 150)
            .frame(width: 350, height: 250) // to simulate outer container dimensions
    }
}

无论您是否使用等宽字体,此答案都有效。

更新:居中第一列

于 2021-09-26T21:45:43.660 回答