如何在SwiftUI中使VStack填充屏幕宽度

huangapple go评论82阅读模式
英文:

How to make VStack fill the width of screen in SwiftUI

问题

我试图创建一个 VStack 示例应用程序,用于可视化 VStack 属性,但我的 VStack 无法填充屏幕的宽度。我在互联网上尝试了许多解决方案(frame 修改器、具有 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")
            }
        }
    }
}

这是结果:

如何在SwiftUI中使VStack填充屏幕宽度

英文:

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] = [&quot;.leading&quot;, &quot;.center&quot;, &quot;.trailing&quot;]
    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(&quot;Controls&quot;)) {
                    VStack(alignment: .leading) {
                        Text(&quot;Spacing: \(Int(spacing))&quot;).font(.caption)
                        HStack {
                            Text(&quot;\(Int(minValue))&quot;)
                            Slider(value: $spacing, in: minValue...maxValue, step: 1)
                            Text(&quot;\(Int(maxValue))&quot;)
                        }
                    }
                    
                    Picker(&quot;alignments&quot;, selection: self.$alignmentIndex) {
                        ForEach(0..&lt;alignments.count) {
                            Text(self.alignments[$0])
                        }
                    }
                    .pickerStyle(SegmentedPickerStyle())

                    Stepper(&quot;Element&#39;s amount: \(elementsAmount)&quot;, value: self.$elementsAmount, in: 0...10)
                }
                
                Section(header: Text(&quot;Canvas&quot;)) {
                    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..&lt;elementsCount, id: \.self) {
                Text(&quot;\($0)th View&quot;)
            }
        }
    }
}

and this is result

如何在SwiftUI中使VStack填充屏幕宽度

答案1

得分: 1

你可以将框架的最大宽度设置为无限 - 这是告诉父视图,此视图希望获得所有可用的宽度的一种方式:

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

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)

答案2

得分: 1

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

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))
            }
        }
    }
}
英文:

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..&lt;elementsCount, id: \.self) {
                Text(&quot;\($0)th View&quot;).frame(maxWidth: .infinity, alignment: Alignment(horizontal: self.alignments[self.alignmentIndex], vertical: .center))
            }
        }
    }
}

huangapple
  • 本文由 发表于 2020年1月6日 20:42:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/59612330.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定