alignmentGuide

9 阅读1分钟

参考链接

隐式 center

⚠️ 红色的线为对齐参考线

截屏2024-08-15 17.42.27.png

struct ImplictDemo: View {
    var body: some View {
        VStack(alignment: .center) {
            LabelView(title: "Authors", color: .green)
                .alignmentGuide(HorizontalAlignment.center, computeValue: { dimension in
                    30
                })
                
            LabelView(title: "Authors", color: .red)
                .alignmentGuide(HorizontalAlignment.center, computeValue: { dimension in
                    90
                })

            LabelView(title: "Authors", color: .blue) // implict guide = d[.center]
        }
        .border(Color.black)
    }
}
struct LabelView: View {
    let title: String
    let color: Color

    var body: some View {
        Text(title)
            .padding(.vertical, 8.0)
            .padding(.horizontal, 40.0)
            .background(color)
            .clipShape(Capsule())
    }
}

隐式 leading

截屏2024-08-15 17.45.20.png

struct ImplictDemo: View {
    var body: some View {
        VStack(alignment: .leading) {
            LabelView(title: "Authors", color: .green)
                .alignmentGuide(.leading, computeValue: { dimension in
                    30
                })
                
            LabelView(title: "Authors", color: .red)
                .alignmentGuide(.leading, computeValue: { dimension in
                    90
                })

            LabelView(title: "Authors", color: .blue) // implict guide = d[.leading]
        }
        .border(Color.black)
    }
}

隐式 traling

截屏2024-08-15 17.47.52.png

struct ImplictDemo: View {
    var body: some View {
        VStack(alignment: .trailing) {
            LabelView(title: "Authors", color: .green)
                .alignmentGuide(.trailing, computeValue: { dimension in
                    30
                })
                
            LabelView(title: "Authors", color: .red)
                .alignmentGuide(.trailing, computeValue: { dimension in
                    90
                })

            LabelView(title: "Authors", color: .blue) // implict guide = d[.trailing]
        }
        .border(Color.black)
    }
}

跨View Alignment

自定义 Align

extension VerticalAlignment {
    struct SelectAlignment: AlignmentID {
        static func defaultValue(in context: ViewDimensions) -> CGFloat {
            context[VerticalAlignment.center]
        }
    }
    static let select = VerticalAlignment(SelectAlignment.self)
}

实现效果

image.png

单击某一行和用户图标对齐

struct AlignCrossView: View {
    @State private var selectedIndex = 0
    let names = [
        "onevcat | Wei Wang",
        "zaq | Hao Zang",
        "tyyqa | Lixiao Yang" 
    ]
    
    var body: some View {
        HStack(alignment: .select) {
            Text("User:")
                .font(.footnote)
                .foregroundColor(.green)
                .alignmentGuide(VerticalAlignment.center, computeValue: { dimension in
                    dimension[.bottom] + CGFloat(self.selectedIndex) * 20.3
                })

            Image(systemName: "person.circle")
                .foregroundColor(.green)
                .alignmentGuide(.select, computeValue: { dimension in
                    dimension[VerticalAlignment.center]
                })
            
            VStack(alignment: .leading) {
                ForEach(0..<names.count, id: \.self) { index in
                    Text(names[index])
                        .foregroundColor(self.selectedIndex == index ? .green : .primary)
                        .onTapGesture {
                            self.selectedIndex = index
                        }
                        .alignmentGuide(self.selectedIndex == index ? .select : .center, computeValue: { dimension in
                            if self.selectedIndex == index {
                                return dimension[VerticalAlignment.center]
                            } else {
                                return 0
                            }
                        })
                }
            }
        }
    }
}

另一个自定义对齐参考

先上默认的布局方式代码

struct CircleButton: View {
    var action: (() -> Void)?
    var symbol: String

    var body: some View {
        ZStack {
            Circle()
                .fill(.gray.opacity(0.5))
            Image(systemName: symbol)
                .font(.system(size: 20))
        }
        .onTapGesture {
            action?()
        }
    }
}
VStack {
    HStack {
        Text("Inbox")
        CircleButton(symbol: "tray.and.arrow.down")
            .frame(width: 50, height: 50)
    }

    HStack {
        Text("Sent")
        CircleButton(symbol: "tray.and.arrow.up")
            .frame(width: 50, height: 50)
    }

    CircleButton(symbol: "line.3.horizontal")
        .frame(width: 60, height: 60)
}

默认布局效果

截屏2024-09-18 14.37.09.png

想要实现的效果:

圆型按钮尾部对齐

截屏2024-09-18 14.32.02.png

VStack(alignment: .menu) {
            HStack {
                Text("Inbox")
                CircleButton(symbol: "tray.and.arrow.down")
                    .frame(width: 50, height: 50)
                    .alignmentGuide(.menu, computeValue: { dimension in
                        dimension[HorizontalAlignment.center]
                    })
            }

            HStack {
                Text("Sent")
                CircleButton(symbol: "tray.and.arrow.up")
                    .frame(width: 50, height: 50)
                    .alignmentGuide(.menu, computeValue: { dimension in
                        dimension[HorizontalAlignment.center]
                    })
            }

            CircleButton(symbol: "line.3.horizontal")
                .frame(width: 60, height: 60)
        }