8

给定一个 HStack,如下所示:

        HStack{
            Text("View1")

            Text("Centre")

            Text("View2")

            Text("View3")
        }

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

4

2 回答 2

11

这是可能的简单方法。使用 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")
                }
            )
        }
    }
}

在相对于另一个居中视图的位置视图中提供了为左/右侧视图提供额外对齐的解决方案

于 2020-06-15T14:32:01.683 回答
8

答案需要几个步骤

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

对于必须填充 VStack 的视图,我使用几何阅读器。这会自动扩展以获取父级的大小,而不会干扰布局。

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))
    }
}

编辑:注意 - 此答案假定您可以设置包含 VStack 的固定高度和宽度。这可以阻止 GeometryReader “推”得太远

在另一种情况下,我将 GeometryReader 替换为一个矩形:

            //rectangle fills the width, then provides a centre for things to align to
            Rectangle()
                .frame(height:0)
                .frame(idealWidth:.infinity)
                .alignmentGuide(.colonCentre) { d in d.width/2 }

注意 - 除非受到限制,否则这仍会扩展到最大宽度!

中心在中心

于 2020-06-15T14:19:50.883 回答