3

如何将Color视图与文本对齐成一条直线?

看起来像这样(文本对齐前导):

█ 红色
█ 绿色
█ 蓝色

或者这个(文本居中对齐):

█ 红色
█ 绿色
█ 蓝色

当前代码:

struct ContentView: View {
    @State private var colorName: Colors = .red
    
    var body: some View {
        Picker("Select color", selection: $colorName) {
            ForEach(Colors.allCases) { color in
                HStack {
                    color.asColor.aspectRatio(contentMode: .fit)
                    
                    Text(color.rawValue)
                }
            }
        }
    }
}


enum Colors: String, CaseIterable, Identifiable {
    case red
    case green
    case blue
    
    var id: String { rawValue }
    var asColor: Color {
        switch self {
        case .red:      return .red
        case .green:    return .green
        case .blue:     return .blue
        }
    }
}

结果(未正确对齐):

结果

没有Picker,我发现可以使用alignmentGuide(_:computeValue:)来实现结果。但是,这需要在Picker.

试图:

VStack(alignment: .custom) {
    ForEach(Colors.allCases) { color in
        HStack {
            color.asColor.aspectRatio(contentMode: .fit)
                .alignmentGuide(.custom) { d in
                    d[.leading]
                }
            
            Text(color.rawValue)
                .frame(maxWidth: .infinity)
                .fixedSize()
        }
    }
    .frame(height: 50)
}

/* ... */

extension HorizontalAlignment {
    struct CustomAlignment: AlignmentID {
        static func defaultValue(in context: ViewDimensions) -> CGFloat {
            return context[HorizontalAlignment.leading]
        }
    }
    
    static let custom = HorizontalAlignment(CustomAlignment.self)
}

尝试结果:

结果 2

4

2 回答 2

3

可能的解决方案是对使用视图首选项计算的最大标签应用的标签使用动态宽度。

这是一个演示。使用 Xcode 13beta / iOS15 测试

演示

注意:ViewWidthKey取自我的其他答案https://stackoverflow.com/a/63253241/12299030

struct ContentView: View {
    @State private var colorName: Colors = .red
    @State private var maxWidth = CGFloat.zero

    var body: some View {
        Picker("Select color", selection: $colorName) {
            ForEach(Colors.allCases) { color in
                HStack {
                    color.asColor.aspectRatio(contentMode: .fit)
                    Text(color.rawValue)
                }
                .background(GeometryReader {
                    Color.clear.preference(key: ViewWidthKey.self, 
                        value: $0.frame(in: .local).size.width)
                })
                .onPreferenceChange(ViewWidthKey.self) {
                    self.maxWidth = max($0, maxWidth)
                }
                .frame(minWidth: maxWidth, alignment: .leading)
            }
        }
    }
}
于 2021-06-15T04:49:35.277 回答
0

我认为这应该对齐您的文本并解决您的问题。

struct ContentView: View {
    @State private var colorName: Colors = .red
    
    var body: some View {
        Picker("Select color", selection: $colorName) {
            ForEach(Colors.allCases) { color in
                HStack() {
                    color.asColor.aspectRatio(contentMode: .fit)
                    
                    Text(color.rawValue)
                        .frame(width: 100, height: 30, alignment: .leading)
                }
            }
        }
    }
}

一个简单的.frame修饰符将解决这些问题,尝试将您的文本框在一起,或者Label如果您不想在涉及选择器或列表视图时使事情复杂化,请使用 a。

如果您确实继续使用此解决方案,请尝试根据您的要求尝试widthheight.leading.trailing

于 2021-06-15T01:08:36.433 回答