使用文本和滑块swiftUI创建垂直堆叠的HSTACK

使用文本和滑块swiftUI创建垂直堆叠的HSTACK,swiftui,Swiftui,嗨,我有一堆由文本和滑块组成的hstack。滑块宽度延伸到它前面文本的边缘,但我希望它们都具有相同的宽度并显示在一个直列中 像下面这样 这就是我如何形成堆栈 VStack { ForEach(defensiveLayers.indices, id: \.self) { i in HStack { Text(defensiveLayers[i].name).font(.custom("Gill Sans&

嗨,我有一堆由文本和滑块组成的hstack。滑块宽度延伸到它前面文本的边缘,但我希望它们都具有相同的宽度并显示在一个直列中

像下面这样

这就是我如何形成堆栈

    VStack {
        ForEach(defensiveLayers.indices, id: \.self) { i in
            HStack {
                Text(defensiveLayers[i].name).font(.custom("Gill Sans", size: 12)).padding(.trailing).foregroundColor(.gray)
                MyNodeView(myNode: $defensiveLayers[i])
            }
        }
    }
这是我正在形成滑块的视图。有人能帮忙吗

struct MyNodeView : View {
    @Binding var myNode : Sliders
    var body: some View {
        HStack {
            Text("\(String(format: "%.f", myNode.percent))%").font(.footnote)
            Slider(value: $myNode.percent, in: 0 ... 100)
        }
    }
    
}

要确保所有文本的宽度相同,最简单的方法是
.frame(宽度:)

结果:


您可以计算最长的
文本所需的宽度,并将该特定宽度应用于所有
HStack
视图中的所有前导
文本
视图,以统一宽度。我创建了一个助手方法,用于查找任何SwiftUI
视图所需的宽度

助手:

extension View {
    func viewSize(onChange: @escaping (CGSize) -> Void) -> some View {
        background(
            GeometryReader { geometryProxy in
                Color.clear
                    .preference(key: SizePreferenceKey.self, value: geometryProxy.size)
            }
        )
        .onPreferenceChange(SizePreferenceKey.self, perform: onChange)
    }
}

private struct SizePreferenceKey: PreferenceKey {
    static var defaultValue: CGSize = .zero
    static func reduce(value: inout CGSize, nextValue: () -> CGSize) { }
}
用法:

@State private var textFrameWidth: CGFloat = 0

var body: some View {
    VStack {
        ForEach(defensiveLayers.indices, id: \.self) { i in
            HStack {
                Text(defensiveLayers[i].name)
                    .font(.custom("Gill Sans", size: 12))
                    .padding(.trailing)
                    .foregroundColor(.gray)
                    .viewSize { size in
                        textFrameWidth = textFrameWidth < size.width ? size.width : textFrameWidth
                    }
                    .frame(width: textFrameWidth)
                MyNodeView(myNode: $defensiveLayers[i])
            }
        }
    }
}
@State private var textFrameWidth:CGFloat=0
var body:一些观点{
VStack{
ForEach(defensiveelayers.index,id:\.self){i in
HStack{
文本(防御装备[i].名称)
.font(.custom(“Gill Sans”,大小:12))
.padding(.training)
.foregroundColor(.灰色)
.viewSize{size in
textFrameWidth=textFrameWidth
嘿,你能正确地提供第一块代码吗?看起来你没有正确地粘贴它。对不起,我不想将整个类粘贴在这里,所以我只是把Vstack组放在这里,我只是更新了它。
@State private var textFrameWidth: CGFloat = 0

var body: some View {
    VStack {
        ForEach(defensiveLayers.indices, id: \.self) { i in
            HStack {
                Text(defensiveLayers[i].name)
                    .font(.custom("Gill Sans", size: 12))
                    .padding(.trailing)
                    .foregroundColor(.gray)
                    .viewSize { size in
                        textFrameWidth = textFrameWidth < size.width ? size.width : textFrameWidth
                    }
                    .frame(width: textFrameWidth)
                MyNodeView(myNode: $defensiveLayers[i])
            }
        }
    }
}