【问题标题】:SwiftUI: make layout relative to a central viewSwiftUI:相对于中心视图进行布局
【发布时间】:2019-08-31 05:39:26
【问题描述】:

假设我构建了一个这样的视图:

struct MyView: View {
   @State private var a: String
   @State private var b: String
   @State private var c: String

   var body: some View {
      VStack {
        HStack {
          Text(a)

          // this is the central view
          Text(b).font(.headline)
        }

        Text(c)
      }
   }
}

我希望中心文本视图(显示 b 的那个)成为布局的锚点。也就是说,无论其他文本值如何变化,我希望中心文本始终保持在MyView 的中心(文本元素的中心和MyView 的中心应该保持相同)和其他文本元素应该围绕中心布置。

如何实现这一目标?我试图查看对齐指南,但我似乎不明白如何正确使用它们。

【问题讨论】:

    标签: layout swiftui


    【解决方案1】:

    在花了一些时间详细了解对齐的工作原理后,我设法找到了一个仅使用堆栈和自定义对齐的解决方案,具有最少的对齐指南并且不需要保存任何中间状态。它纯粹是声明性的,所以我想这就是 SwiftUI 设计师的意图。我仍然认为它可能有更好的设计,但可以使用它。

    struct ContentView: View {
        @State var a: String = "AAAAA"
        @State var b: String = "BBBB"
        @State var c: String = "CCCCCC"
    
        var body: some View {
             VStack {
                ZStack(alignment: .mid) {
                    // create vertical and horizontal 
                    // space to align to
                    HStack { Spacer() }
                    VStack { Spacer() }
    
                    VStack(alignment: .midX) {
                        Text(self.a)
    
                        HStack(alignment: .center) {
                            Text(self.c)
    
    
                            Text(self.b)
                                .font(.title)
                                .border(Color.blue)
                                .alignmentGuide(.midX) { d in
                                    (d[.leading] + d[.trailing])/2
                                }
                                .alignmentGuide(.midY) { d in
                                    (d[.top] + d[.bottom])/2
                                }
                        }
                    }
                }
                .layoutPriority(1.0)
                .overlay(CrossHair().stroke(Color.pink, lineWidth: 2))
    
                TextField("", text: self.$b).textFieldStyle(RoundedBorderTextFieldStyle())
            }
        }
    }
    
    fileprivate extension HorizontalAlignment {
        enum MidX : AlignmentID {
            static func defaultValue(in d: ViewDimensions) -> CGFloat {
                return (d[.leading] + d[.trailing])/2
            }
        }
    
        static let midX = HorizontalAlignment(MidX.self)
    }
    
    fileprivate extension VerticalAlignment {
        enum MidY : AlignmentID {
            static func defaultValue(in d: ViewDimensions) -> CGFloat {
                return (d[.top] + d[.bottom])/2
            }
        }
    
        static let midY = VerticalAlignment(MidY.self)
    }
    
    fileprivate extension Alignment {
        static let mid = Alignment(horizontal: .midX, vertical: .midY)
    

    【讨论】:

    • @kontiki 感谢您富有洞察力的 cmets 和提示。我想我设法通过消除对hs 状态的需要来稍微改进您的解决方案,但大部分功劳肯定归功于您:)
    猜你喜欢
    • 1970-01-01
    • 2017-01-20
    • 2016-11-25
    • 1970-01-01
    • 2019-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-04
    相关资源
    最近更新 更多