SwiftUI:如何强制 HStack 中的特定视图位于中心

Con*_*lon 6 alignment swiftui hstack

给定一个 HStack,如下所示:

        HStack{
            Text("View1")

            Text("Centre")

            Text("View2")

            Text("View3")
        }
Run Code Online (Sandbox Code Playgroud)

如何强制“中心”视图位于中心?

Asp*_*eri 7

这是可能的简单方法。使用 Xcode 11.4 / iOS 13.4 测试

演示

struct DemoHStackOneInCenter: View {
    var body: some View {
        HStack{
            Spacer().overlay(Text("View1"))

            Text("Centre")

            Spacer().overlay(
                HStack {
                    Text("View2")
                    Text("View3")
                }
            )
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

相对于另一个居中视图的位置视图中提供了具有左/右侧视图附加对齐的解决方案

  • 这是一个有趣的方法。它确实会弄乱视图之间的间距,但您可以通过左/右 HStack 中的更多间隔和显式间距来修复此问题。 (2认同)

Con*_*lon 6

答案需要几个步骤

  1. 将 HStack 包装在 VStack 中。VStack 可以控制它的孩子的水平对齐方式
  2. 将自定义对齐指南应用于 VStack
  3. 创建一个占据全宽的 VStack 的子视图。将自定义对齐指南固定到此视图的中心。(这将对齐指南固定到 VStack 的中心)
  4. 将“中心”视图的中心与对齐指南对齐

对于必须填充 VStack 的视图,我使用了 Geometry Reader。这会自动扩展以采用父级的大小,而不会以其他方式干扰布局。

import SwiftUI


//Custom Alignment Guide
extension HorizontalAlignment {
    enum SubCenter: AlignmentID {
        static func defaultValue(in d: ViewDimensions) -> CGFloat {
            d[HorizontalAlignment.center]
        }
    }

    static let subCentre = HorizontalAlignment(SubCenter.self)
}

struct CentreSubviewOfHStack: View {
    var body: some View {
        //VStack Alignment set to the custom alignment
        VStack(alignment: .subCentre) {
            HStack{
                Text("View1")

                //Centre view aligned
                Text("Centre")
                .alignmentGuide(.subCentre) { d in d.width/2 }

                Text("View2")

                Text("View3")
            }

            //Geometry reader automatically fills the parent
            //this is aligned with the custom guide
            GeometryReader { geometry in
                EmptyView()
            }
            .alignmentGuide(.subCentre) { d in d.width/2 }
        }
    }
}

struct CentreSubviewOfHStack_Previews: PreviewProvider {
    static var previews: some View {
        CentreSubviewOfHStack()
            .previewLayout(CGSize.init(x: 250, y: 100))
    }
}
Run Code Online (Sandbox Code Playgroud)

中心在中心