【问题标题】:How to make VStack fill the width of screen in SwiftUI如何使 VStack 在 SwiftUI 中填充屏幕的宽度
【发布时间】:2020-04-24 00:14:51
【问题描述】:

我正在尝试制作可视化 VStack 属性的 VStack 示例应用程序

但我的 VStack 无法填满屏幕宽度

我在互联网上尝试了许多解决方案(框架修改器、带 Spacer 的 HStack、GeometryReader),但它们都不起作用

这是我的代码

父视图

struct LayoutView: View {

    @State private var spacing: CGFloat = 0.0
    @State private var alignmentIndex = 0
    @State private var elementsAmount = 0

    private let layout: StackLayout

    private let alignments: [String] = [".leading", ".center", ".trailing"]
    private let minValue: CGFloat = 0.0
    private let maxValue: CGFloat = 100.0

    init(_ layout: StackLayout) {
        self.layout = layout
    }

    var body: some View {
        NavigationView {
            Form {
                Section(header: Text("Controls")) {
                    VStack(alignment: .leading) {
                        Text("Spacing: \(Int(spacing))").font(.caption)
                        HStack {
                            Text("\(Int(minValue))")
                            Slider(value: $spacing, in: minValue...maxValue, step: 1)
                            Text("\(Int(maxValue))")
                        }
                    }

                    Picker("alignments", selection: self.$alignmentIndex) {
                        ForEach(0..<alignments.count) {
                            Text(self.alignments[$0])
                        }
                    }
                    .pickerStyle(SegmentedPickerStyle())

                    Stepper("Element's amount: \(elementsAmount)", value: self.$elementsAmount, in: 0...10)
                }

                Section(header: Text("Canvas")) {
                    VStackView(spacing: $spacing, alignmentIndex: $alignmentIndex, elementsCount: $elementsAmount)
                }
            }
            .navigationBarTitle(Text(layout.rawValue), displayMode: .inline)
        }
    }
}

子视图

struct VStackView: View {
    @Binding var spacing: CGFloat
    @Binding var alignmentIndex: Int
    @Binding var elementsCount: Int

    private let alignments: [HorizontalAlignment] = [.leading, .center, .trailing]

    var body: some View {
        VStack(alignment: self.alignments[alignmentIndex], spacing: CGFloat(spacing)) {
            ForEach(0..<elementsCount, id: \.self) {
                Text("\($0)th View")
            }
        }
    }
}

这是结果

【问题讨论】:

    标签: ios swift swiftui vstack


    【解决方案1】:

    您可以将框架的 maxWidth 设置为无穷大 - 这是一种告诉父视图该视图想要它可以获得的所有宽度的方式:

    VStack {
        //...
    }  .frame(maxWidth: .infinity)
    

    【讨论】:

      【解决方案2】:

      我猜你可以像这样更新代码

      struct VStackView: View {
          @Binding var spacing: CGFloat
          @Binding var alignmentIndex: Int
          @Binding var elementsCount: Int
      
          private let alignments: [HorizontalAlignment] = [.leading, .center, .trailing]
      
          var body: some View {
              VStack(alignment: self.alignments[alignmentIndex], spacing: CGFloat(spacing)) {
                  ForEach(0..<elementsCount, id: \.self) {
                      Text("\($0)th View").frame(maxWidth: .infinity, alignment: Alignment(horizontal: self.alignments[self.alignmentIndex], vertical: .center))
                  }
              }
          }
      }
      

      【讨论】:

      • 哦!它有效,但Alignment(horizontal: self.alignments[self.alignmentIndex], vertical: .center) 如何使它正确?如果我设置这个只是 .topLeading 它不起作用
      • 我猜这不是真正的VStack对齐,实际上它是Text的对齐,使它看起来像VStack对齐。对吗?
      • @DongkunLee 确切地说,VStack 垂直视图(这就是间距起作用的原因),但您想显示对齐选项,它仅适用于 Text