1

I'm trying to make VStack Sample app which visualize VStack Properties

but my VStack couldn't fill the width of screen

I tried many solutions on internet (frame modifier, HStack with Spacer, GeometryReader) but they were not work

This is my code

Parent View

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)
        }
    }
}

Child View

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")
            }
        }
    }
}

and this is result

enter image description here

PrepareFor
  • 2,448
  • 6
  • 22
  • 36

2 Answers2

1

You can set maxWidth of the frame to infinity - it is a way of telling the parent view that this view wants all the width it can get:

VStack {
    //...
}  .frame(maxWidth: .infinity)
LuLuGaGa
  • 13,089
  • 6
  • 49
  • 57
1

I guess you can update code like this

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))
            }
        }
    }
}
Vadim Nikolaev
  • 2,132
  • 17
  • 34
  • Oh! it works, but how `Alignment(horizontal: self.alignments[self.alignmentIndex], vertical: .center)` make it correct? if I set this just .topLeading it's not work – PrepareFor Jan 07 '20 at 01:29
  • I guess it is not the real alignment of VStack, Actually it is a alignment of Text and make it looks like VStack alignment. is it correct? – PrepareFor Jan 07 '20 at 01:33
  • @DongkunLee exactly, `VStack` views vertically (that's why spacing is working), but you want to show alignment option, and it applies just to `Text` – Vadim Nikolaev Jan 08 '20 at 06:20