【问题标题】:Align views in Picker在选取器中对齐视图
【发布时间】:2021-06-14 23:34:58
【问题描述】:

如何将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)
}

尝试结果:

【问题讨论】:

    标签: swift swiftui swiftui-picker


    【解决方案1】:

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

    这是一个演示。使用 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)
                }
            }
        }
    }
    

    【讨论】:

    • 完美运行!我毫无疑问地知道,如果有人能解决它……那就是 Asperi :)
    【解决方案2】:

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

    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

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

    【讨论】:

    • 我的问题的原始编辑使用Label,因为我不知道有人会如何解决问题,所以我切换了它。虽然这主要解决了这个问题,但最好有一些居中的东西并使用对齐指南之类的东西,所以我不需要硬编码任何尺寸。实际上我有比这更多的项目,这只是一个最小的例子。不过还是谢谢你的回答!基本上选择器中最宽的项目会保留,其他所有内容都与此对齐。
    • 如果你想要居中的项目而不是前导,使用框架,框架的作用是将整个文本保持在高度 * 宽度空间内,所以我要做的是看看最大的颜色是什么您拥有的长度并基于该长度设置帧大小。我很少使用对齐指南,因为我不需要它们,但也许其他人可以帮助你。
    • 问题是它应该适应不同的字体大小等:/
    • 添加了alignmentGuide 的尝试,在不使用Picker 时有效。
    猜你喜欢
    • 1970-01-01
    • 2013-06-15
    • 1970-01-01
    • 2017-12-08
    • 1970-01-01
    • 2017-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多