【问题标题】:Left and right padding (not leading and trailing) in SwiftUISwiftUI 中的左右填充(不是前导和尾随)
【发布时间】:2021-11-07 15:03:36
【问题描述】:

SwiftUI 中的填充修饰符采用EdgeInsets,例如

.padding(.leading, 8)

但是,只有前导和尾随的 EdgeInsets,而不是左右。这带来了一个问题,因为并非 RTL 语言中的所有内容都必须与 LTR 语言中的显示方式相反。

有没有办法实现与填充修饰符相同或相似的效果,无论语言的方向如何,它都会强制填充在左侧或右侧?

【问题讨论】:

    标签: ios swiftui padding right-to-left


    【解决方案1】:

    这是一个可能的方法的简化演示 - 使用在每一侧注入固定大小的Spacer 的扩展。

    使用 Xcode 13 / iOS 15 准备和测试

    enum Side: Equatable, Hashable {
        case left
        case right
    }
    
    extension View {
        func padding(sides: [Side], value: CGFloat = 8) -> some View {
            HStack(spacing: 0) {
                if sides.contains(.left) {
                    Spacer().frame(width: value)
                }
                self
                if sides.contains(.right) {
                    Spacer().frame(width: value)
                }
            }
        }
    }
    

    使用演示

    var body: some View {
      TextField("Last Name", text: $nameLast)
        .textFieldStyle(.roundedBorder)
        .padding(sides: [.left], value: 20)
    }
    

    【讨论】:

    • 事实上,您的解决方案根本不起作用。你在 RTL 上试过吗?见this exampleHStack 子代的顺序与 RTL 交换。
    【解决方案2】:

    使用@Environment(\.layoutDirection) 获取当前布局方向(LTR 或 RTL)并根据需要使用它来翻转.leading.trailing

    这是一个ViewModifier,可以方便地包装所有内容:

    enum NoFlipEdge {
        case left, right
    }
    
    struct NoFlipPadding: ViewModifier {
        let edge: NoFlipEdge
        let length: CGFloat?
        @Environment(\.layoutDirection) var layoutDirection
        
        private var computedEdge: Edge.Set {
            if layoutDirection == .rightToLeft {
                return edge == .left ? .trailing : .leading
            } else {
                return edge == .left ? .leading : .trailing
            }
        }
        
        func body(content: Content) -> some View {
            content
                .padding(computedEdge, length)
        }
    }
    
    extension View {
        func padding(_ edge: NoFlipEdge, _ length: CGFloat? = nil) -> some View {
            self.modifier(NoFlipPadding(edge: edge, length: length))
        }
    }
    

    像使用标准填充修饰符一样使用它:

    Text("Text")
        .padding(.left, 10)
    

    【讨论】:

    • layoutDirection 是可读写的 env 值,所以让我们想象一下,如果父视图中的某个人需要故意将其更改为与当前系统相反的值会发生什么。
    • @Asperi 如果你担心 layoutDirection 会被覆盖,你可以检查这个全局设置而不是环境值:UIApplication.shared.userInterfaceLayoutDirection == .rightToLeft
    • @Asperi 实际上 padding(.leading) 取决于 @Environment(\.layoutDirection),所以如果你改变它 - 这个修饰符仍然会给出正确的填充。
    • @Philip 你说得对,我误读了@Asperi 的问题。无论如何,我的解决方案都应该有效。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-06-27
    • 2021-03-19
    • 2021-11-16
    • 2014-10-11
    • 2019-10-30
    • 1970-01-01
    相关资源
    最近更新 更多