SwiftUI 中的左右填充(不是前导和尾随)
Left and right padding (not leading and trailing) in SwiftUI
SwiftUI 中的填充修饰符采用 EdgeInsets
,例如
.padding(.leading, 8)
但是,只有前导和尾随的EdgeInsets,没有左和右。这带来了一个问题,因为并非 RTL 语言中的所有内容都应该与它在 LTR 语言中的显示方式相反。
有没有办法实现与 padding 修饰符相同或相似的效果,它强制 padding 在左侧或右侧,而不管语言的方向性如何?
这是可能方法的简化演示 - 使用扩展,在每一侧注入固定大小 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)
}
使用@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)
对我来说是
VStack(alignment: .center) {
Text("Car")
.font(.body)
.foregroundColor(.black)
}
.padding(.trailing, 5)
SwiftUI 中的填充修饰符采用 EdgeInsets
,例如
.padding(.leading, 8)
但是,只有前导和尾随的EdgeInsets,没有左和右。这带来了一个问题,因为并非 RTL 语言中的所有内容都应该与它在 LTR 语言中的显示方式相反。
有没有办法实现与 padding 修饰符相同或相似的效果,它强制 padding 在左侧或右侧,而不管语言的方向性如何?
这是可能方法的简化演示 - 使用扩展,在每一侧注入固定大小 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)
}
使用@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)
对我来说是
VStack(alignment: .center) {
Text("Car")
.font(.body)
.foregroundColor(.black)
}
.padding(.trailing, 5)