在 SwiftUI 中对齐 HStack,但大小不相等

Posted

技术标签:

【中文标题】在 SwiftUI 中对齐 HStack,但大小不相等【英文标题】:Aligning HStack without equal sizing in SwiftUI 【发布时间】:2019-06-09 07:42:00 【问题描述】:

我有一个自定义图表,其中包含一些文本,如下所示。它正确对齐第一个文本,它错误地对齐最后一个文本。我需要带有文本的 VStack 像手风琴一样拉伸,以便最后一个文本的 centerY 与图表底部对齐。

正如蓝色 Xcode 突出显示的那样,VStack 接收到与带有偏移量的图表相同的大小。

为了对齐第一个文本,我扩展了 VerticalAlignment,如 WWDC 2019 - Session 237 所示。

extension VerticalAlignment 
   private enum TopChartAndMidTitle: AlignmentID 
      static func defaultValue(in dimensions: ViewDimensions) -> Length 
         return dimensions[.top]
      
   
   static let topChartAndMidTitle = VerticalAlignment(TopChartAndMidTitle.self)

然后我是这样使用的:

var labels = ["1900", "1800", "1700", "1600", "1500", "1400"]

var body: some View 
    HStack(alignment: .topChartAndMidTitle) 
        chart()
            .alignmentGuide(.topChartAndMidTitle)  $0[.top] 
        valueLabels()
    


private func valueLabels() -> AnyView 
    AnyView(VStack 
        Text(labels[0]).font(.footnote)
            .alignmentGuide(.topChartAndMidTitle)  $0[.bottom] / 2 
        ForEach(labels.dropFirst().identified(by: \.self))  label in
            Spacer()
            Text(label).font(.footnote)
        
    )

问题:如何将最后一个文本与图表底部对齐,从而拉伸 VStack?

要对此进行测试,只需将我的自定义图表替换为 Rectangle().fill(Color.red)。这会导致同样的问题。

【问题讨论】:

我不认为您可以为每个标签进行自定义对齐,您需要为每对(chartRow、标签)设置一个 HStack。您可以尝试为最后一个标签设置正确的对齐方式(您只为第一个标签设置了正确的对齐方式),并希望标签会自动排列以覆盖其间的空闲空间。您也可以尝试在标签 VStack 中使用空格修饰符 只要第一个和最后一个标签对齐,其他标签也将对齐。我只做了第一个,因为我找不到同时做第一个和最后一个的方法。我愿意接受任何可行的方法。 【参考方案1】:

今天我会用下面的方法来做...

结果演示

代码(TopChartAndMidTitle“原样”用于原始问题)

struct TestAlignScales: View 
    var labels = ["1900", "1800", "1700", "1600", "1500", "1400"]

    @State private var graphHeight = CGFloat.zero
    var body: some View 
        HStack(alignment: .topChartAndMidTitle) 
            Rectangle().fill(Color.red)
                .alignmentGuide(.topChartAndMidTitle)  d in
                    if self.graphHeight != d.height 
                        self.graphHeight = d.height
                    
                    return d[.top]
                
            valueLabels()
        
    

    @State private var delta = CGFloat.zero
    private func valueLabels() -> some View 
        VStack 
            ForEach(labels, id: \.self)  label in
                VStack 
                    if label == self.labels.first! 
                        Text(label).font(.footnote)
                            .alignmentGuide(.topChartAndMidTitle)  d in
                                if self.delta != d.height 
                                    self.delta = d.height
                                
                                return d[VerticalAlignment.center]
                            
                     else 
                        Text(label).font(.footnote)
                    
                    if label != self.labels.last! 
                        Spacer()
                    
                
            
        
        .frame(height: graphHeight + delta)
    



struct TestAlignScales_Previews: PreviewProvider 
    static var previews: some View 
        TestAlignScales()
            .frame(height: 400)
    

【讨论】:

太棒了。感谢您迟到的回复。我会试试这个。基本上,在那篇文章之后,我放弃了用 SwiftUI 编写整个应用程序。它只是觉得它太局限了,无论我多么尝试拆分我的代码,它仍然最终成为一个混乱的厄运金字塔。

以上是关于在 SwiftUI 中对齐 HStack,但大小不相等的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI:底部对齐不同帧大小的文本和图像

SwiftUI HStack 文本未对齐

Swiftui - ***选择器,更改对齐方式和字体大小

如何将项目 HStack 与 VStack SwiftUI 对齐

SwiftUI在多个HStacks中对齐不同长度的文本

ScrollView 文本对齐 SwiftUI