swiftUI 使用文本和滑块创建垂直堆栈的 HStack

时间:2021-05-16 19:24:06

标签: swiftui

嗨,我有一堆由文本和滑块组成的 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)
        }
    }
    
}

2 个答案:

答案 0 :(得分:1)

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

struct Sliders {
    var name = "Name"
    var percent = CGFloat(100)
}
struct ContentView: View {
    
    @State var defensiveLayers = [
        Sliders(name: "Long name", percent: 80),
        Sliders(name: "Name", percent: 70),
        Sliders(name: "Ok name", percent: 65),
        Sliders(name: "Hi", percent: 15),
        Sliders(name: "Hello", percent: 45),
    ]
    
    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)
                        .frame(width: 100) /// add frame here!
                    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)
        }
    }
}

结果:

Vertical stack sliders with text on left. Each slider's left position is the same no matter the text's length.

答案 1 :(得分:0)

您可以计算最长 Text 所需的宽度,并将该特定宽度应用于所有 Text 中的所有前导 HStack 视图,并在宽度上统一它们。我已经创建了一个帮助方法来查找任何 SwiftUI View 所需的宽度。

助手:

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