根据布局方向翻转 SwiftUI 形状

Flip a SwiftUI Shape based on layout direction

我制作了一个 SemiRoundedRectangle 形状,我用它来剪裁侧边菜单。如果用户使用 RTL 语言,我需要翻转它,但不确定实现此目的的最佳方法。

我试过 .flipsForRightToLeftLayoutDirection(true) 但这也会翻转实际的阿拉伯语文本。当我尝试旋转形状时,它不再符合 Shape 协议,因此我不能再在 .clipShape 中使用它。当我切换到阿拉伯语时,SwiftUI 中的其他所有内容都会神奇地自行翻转,是否可以添加一些东西到我的形状中以赋予它这些魔力?

感谢您的帮助:)


import SwiftUI

struct SemiRoundedRectangle: Shape {
    var cornerRadius: CGFloat
    func path(in rect: CGRect) -> Path {
        var path = Path()
        path.move(to: CGPoint(x: rect.maxX, y: rect.minY))
        path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
        path.addLine(to: CGPoint(x: rect.minX+cornerRadius, y: rect.maxY))
        path.addArc(center: CGPoint(x: cornerRadius, y: rect.height - cornerRadius),
                    radius: cornerRadius,
                    startAngle: .degrees(90),
                    endAngle: .degrees(180), clockwise: false)
        path.addLine(to: CGPoint(x: 0, y: cornerRadius))
        path.addArc(center: CGPoint(x: cornerRadius, y: cornerRadius),
                    radius: cornerRadius,
                    startAngle: .degrees(180),
                    endAngle: .degrees(270), clockwise: false)
        path.addLine(to: CGPoint(x: rect.maxX, y: rect.minY))
        
        return path
    }

}

struct TestView {
    var body: some View {
        HStack {
            Text("ايه الأخبار؟")
            .padding()
            .background(Color.green)
            .clipShape(SemiRoundedRectangle(cornerRadius: 10.0))
            
            Spacer()
        }
        
    }
}

尝试将 clipShape 附加到 Color.green

struct TestView: View {
    var body: some View {
        HStack {
            Text("ايه الأخبار؟")
            .padding()
            .background(
                Color.green /// here!
                    .clipShape(SemiRoundedRectangle(cornerRadius: 10.0))
                    .flipsForRightToLeftLayoutDirection(true)
            )
            
            Spacer()
        }
    }
}

结果:

English RTL Language

有一个通用的解决方案:

extension Shape {
    func flipped(_ axis: Axis = .horizontal, anchor: UnitPoint = .center) -> ScaledShape<Self> {
        switch axis {
        case .horizontal:
            return scale(x: -1, y: 1, anchor: anchor)
        case .vertical:
            return scale(x: 1, y: -1, anchor: anchor)
        }
        
    }
}

用于这种情况:

struct TestView: View {
    var body: some View {
        HStack {
            Text("ايه الأخبار؟")
                .padding()
                .background(Color.green)
                .clipShape(SemiRoundedRectangle(cornerRadius: 20.0).flipped())
            Spacer()
        }
        .padding()
    }
}