首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SwiftUI自定义对齐可将视图推送到比父视图更宽的位置

SwiftUI自定义对齐可将视图推送到比父视图更宽的位置
EN

Stack Overflow用户
提问于 2020-02-01 05:16:15
回答 2查看 898关注 0票数 4

我从这个开始。一些带有两个滑块的UI。

由以下代码定义:

代码语言:javascript
复制
struct ContentView: View {
    @State private var num1: Double = 0.5
    @State private var num2: Double = 0.5
    let blueGreen = Color(red: 0.2, green: 0.6, blue: 0.6)
    var body: some View {
        VStack {
            Circle().fill(blueGreen).border(Color.blue, width: 1.0).padding(4.0)
            VStack {
                HStack {
                    Text("Value:")
                    Slider(value: $num1, in: 0...1)
                }
                HStack {
                    Text("Opacity:")
                    Slider(value: $num2, in: 0...1)
                }
            }
            Spacer()
        }.border(Color.green, width: 1.0).padding()
    }
}

我希望"Value:“和"Opacity:”标签在它们的尾部边缘对齐,使滑块排列整齐且宽度相同。我听说自定义对齐可以像这样对齐视图,不是同级的视图。

因此,我添加了自定义对齐:

代码语言:javascript
复制
extension HorizontalAlignment {
    private enum MyAlignment : AlignmentID {
        static func defaultValue(in d: ViewDimensions) -> CGFloat {
            return d[.trailing]
        }
    }
    static let myAlignment = HorizontalAlignment(MyAlignment.self)
}

struct ContentView: View {
    @State private var num1: Double = 0.5
    @State private var num2: Double = 0.5
    let blueGreen = Color(red: 0.2, green: 0.6, blue: 0.6)
    var body: some View {
        VStack {
            Circle().fill(blueGreen).border(Color.blue, width: 1.0).padding(4.0)
            VStack(alignment: .myAlignment) {
                HStack {
                    Text("Value:").alignmentGuide(.myAlignment) { d in d[.trailing] }
                    Slider(value: $num1, in: 0...1)
                }
                HStack {
                    Text("Opacity:").alignmentGuide(.myAlignment) { d in d[.trailing] }
                    Slider(value: $num2, in: 0...1)
                }
            }
            Spacer()
        }.border(Color.green, width: 1.0).padding()
    }
}

这在一定程度上是可行的。标签的尾部边缘对齐了,但现在UI已部分移出屏幕,向右移动。

使用UIKit和自动布局,我会约束这两个标签的后缘相等。这不会将任何东西推出屏幕(假设一切都像往常一样被限制在屏幕边缘)。这里出了什么问题?如何通过对齐,或者通过更好的方式,使用SwiftUI来实现这一点?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-02-04 17:41:17

一种方法是使用Preferences (了解更多here)。

代码语言:javascript
复制
struct ContentView: View {
    @State private var num1: Double = 0.5
    @State private var num2: Double = 0.5
    @State private var sliderWidth: CGFloat = 0

    private let spacing: CGFloat = 5
    let blueGreen = Color(red: 0.2, green: 0.6, blue: 0.6)

    var body: some View {
        VStack {
            Circle().fill(blueGreen).border(Color.blue, width: 1.0).padding(4.0)

            VStack(alignment: .trailing) {
                HStack(spacing: self.spacing) {
                    Text("Value:")
                        .fixedSize()
                        .anchorPreference(key: MyPrefKey.self, value: .bounds, transform: { [$0] })

                    Slider(value: $num1, in: 0...1)
                        .frame(width: sliderWidth)
                }
                .frame(maxWidth: .infinity, alignment: .trailing)


                HStack(spacing: self.spacing) {
                    Text("Opacity:")
                        .fixedSize()
                        .anchorPreference(key: MyPrefKey.self, value: .bounds, transform: { [$0] })

                    Slider(value: $num2, in: 0...1)
                        .frame(width: sliderWidth)
                }
                .frame(maxWidth: .infinity, alignment: .trailing)

            }
            .backgroundPreferenceValue(MyPrefKey.self) { prefs -> GeometryReader<AnyView> in

               GeometryReader { proxy -> AnyView in
                    let vStackWidth = proxy.size.width

                    let maxAnchor = prefs.max {
                        return proxy[$0].size.width < proxy[$1].size.width

                    }

                    DispatchQueue.main.async {
                        if let a = maxAnchor {
                            self.sliderWidth = vStackWidth - (proxy[a].size.width + self.spacing)

                        }
                    }

                    return AnyView(EmptyView())

                }
            }

            Spacer()

        }.border(Color.green, width: 1.0).padding(20)
    }

}

struct MyPrefKey: PreferenceKey {
    typealias Value = [Anchor<CGRect>]

    static var defaultValue: [Anchor<CGRect>] = []

    static func reduce(value: inout [Anchor<CGRect>], nextValue: () -> [Anchor<CGRect>]) {
        value.append(contentsOf: nextValue())
    }
}
票数 1
EN

Stack Overflow用户

发布于 2020-02-01 17:06:29

好吧,我同意苹果似乎忘记了在SwiftUI中给我们提供一些带有自动布局引擎的东西,比如内容拥抱优先级,抵抗压缩,相等大小,等等。

在SwiftUI对齐指南中,它们不会改变视图大小,只是将视图“按原样”对齐到指定的锚点(如果容器的大小不受限制,则展开容器,因为默认情况下,容器紧凑到内容,这就是您看到的内容)。因此,为了解决所考虑的情况,它需要以某种方式限制(或改变)大小。

下面的代码不是完整的解决方案(它没有考虑到可能的l10n),但显示了方向-由于Slider没有默认大小,所以应该限制一些如何不展开容器。

不管怎样,我会考虑下面的变通方法。(宽度的计算可能更准确、更复杂,比如get frame of Text,例如:通过锚定首选项,然后从考虑填充的可用几何图形代理宽度中减去,但这仍然是相同的-显式指定图幅宽度)。

代码语言:javascript
复制
struct HueSaturationView : View {
    @State private var num1: Double = 0.5
    @State private var num2: Double = 0.5
    let blueGreen = Color(red: 0.2, green: 0.6, blue: 0.6)
    var body: some View {
        GeometryReader { gp in
            VStack {
                Circle().fill(self.blueGreen).border(Color.blue, width: 1.0).padding(4.0)
                VStack(alignment: .myAlignment) {
                    HStack {
                        Text("Value:").alignmentGuide(.myAlignment) { d in d[.trailing] }
                        Slider(value: self.$num1, in: 0...1)
                            .frame(width: gp.size.width * 2/3)
                    }
                    HStack {
                        Text("Opacity:").alignmentGuide(.myAlignment) { d in d[.trailing] }
                        Slider(value: self.$num2, in: 0...1)
                            .frame(width: gp.size.width * 2/3)
                    }
                }
                Spacer()
            }
            .border(Color.green, width: 1.0).padding()
        }
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60011333

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档