首页 > 解决方案 > 在 SwiftUI 中对齐 HStack,但大小不相等

问题描述

我有一个带有一些文本的自定义图表,如下所示。它正确地对齐第一个文本,它不正确地对齐最后一个文本。我需要带有文本的 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). 这将导致同样的问题。

标签: iosswiftswiftui

解决方案


今天我会用以下方法来做......

结果演示

SwiftUI 图形缩放自定义对齐

代码(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)
    }
}

推荐阅读