考虑到无限范围的设备宽度,此处建议的填充解决方案没有意义。我们需要一个能够满足所有类型设备尺寸的解决方案,并且可以保留内容的可读宽度。
最终结果可以由任何视图以 SwiftUI 友好的方式使用:
SomeReallyLongView()
.readableGuidePadding()
Run Code Online (Sandbox Code Playgroud)
首先,我们需要一个ViewModifier可以将视图宽度固定为最大边距的控件。UIKit 实际上将可读内容宽度定义为 672,所以让我们使用它。
SomeReallyLongView()
.readableGuidePadding()
Run Code Online (Sandbox Code Playgroud)
现在我们有了一个修改器,可以将内容剪辑为 672 点宽,并在需要时使用水平间隔符。请注意,我们使用 minLength 0,否则在较小的屏幕上总会有水平填充。我们不希望这样。
现在我们可以创建一个方便的视图扩展来使用我们的修饰符:
private struct ReadableGuidePadding: ViewModifier {
func body(content: Content) -> some View {
HStack(spacing: 0) {
Spacer(minLength: 0)
content.frame(maxWidth: 672)
Spacer(minLength: 0)
}
}
}
Run Code Online (Sandbox Code Playgroud)
享受
其他解决方案对我不起作用,因为它们依赖于硬编码的填充量或下拉到 UIKit,这对于需要在所有不同尺寸的 iPhone、iPad、和苹果电脑。因此,由于仍然没有本地 SwiftUI 等效项(截至 iOS 15/macOS 12),我想我应该做一个替代方案。
我的替代方法是根据以下内容计算填充量:
struct ReadabilityPadding: ViewModifier {
let isEnabled: Bool
@ScaledMetric private var unit: CGFloat = 20
func body(content: Content) -> some View {
// Use a GeometryReader here to get view width.
GeometryReader { geometryProxy in
content
.padding(.horizontal, padding(for: geometryProxy.size.width))
}
}
private func padding(for width: CGFloat) -> CGFloat {
guard isEnabled else { return 0 }
// The internet seems to think the optimal readable width is 50-75
// characters wide; I chose 70 here. The `unit` variable is the
// approximate size of the system font and is wrapped in
// @ScaledMetric to better support dynamic type. I assume that
// the average character width is half of the size of the font.
let idealWidth = 70 * unit / 2
// If the width is already readable then don't apply any padding.
guard width >= idealWidth else {
return 0
}
// If the width is too large then calculate the padding required
// on either side until the view's width is readable.
let padding = round((width - idealWidth) / 2)
return padding
}
}
Run Code Online (Sandbox Code Playgroud)
以下是它在不同设备上的外观(顶部是正常的,底部是应用了 ReadabilityPadding 视图修饰符的):