ios - 复杂视图中的 SwiftUI 字体缩放
问题描述
我的目标是确保容器中的文本根据其父级进行缩放。当容器只包含一个 Text 视图时效果很好,如下所示:
import SwiftUI
struct FontScalingExperiment: View {
var body: some View {
Text("Hello World ~!")
.font(.system(size: 500))
.minimumScaleFactor(0.01)
.lineLimit(1)
.padding()
.background(
RoundedRectangle(cornerRadius: 20)
.fill(Color.yellow)
.scaledToFill()
)
}
}
struct FontScalingExperiment_Previews: PreviewProvider {
static var previews: some View {
Group {
FontScalingExperiment()
.previewLayout(.fixed(width: 100, height: 100))
FontScalingExperiment()
.previewLayout(.fixed(width: 200, height: 200))
FontScalingExperiment()
.previewLayout(.fixed(width: 300, height: 300))
FontScalingExperiment()
.previewLayout(.fixed(width: 400, height: 400))
}
}
}
结果:
但是,当我们有更复杂的 View 时,我们不能使用相同的方法来根据其父大小自动缩放文本,例如:
import SwiftUI
struct IndicatorExperiment: View {
var body: some View {
VStack {
HStack {
Text("Line 1")
Spacer()
}
Spacer()
VStack {
Text("Line 2")
Text("Line 3")
}
Spacer()
Text("Line 4")
}
.padding()
.background(
RoundedRectangle(cornerRadius: 20)
.fill(Color.yellow)
)
.aspectRatio(1, contentMode: .fit)
}
}
struct IndicatorExperiment_Previews: PreviewProvider {
static var previews: some View {
Group {
IndicatorExperiment()
.previewLayout(.fixed(width: 100, height: 100))
IndicatorExperiment()
.previewLayout(.fixed(width: 200, height: 200))
IndicatorExperiment()
.previewLayout(.fixed(width: 300, height: 300))
IndicatorExperiment()
.previewLayout(.fixed(width: 400, height: 400))
}
}
}
只需添加这 3 个修饰符:
.font(.system(size: 500))
.minimumScaleFactor(0.01)
.lineLimit(1)
不会像第一个例子那样产生结果;文本放大超出框架。我成功了,使用 GeometryReader 产生了我想要的结果,然后根据geometry.size.width
. 这是在 SwiftUI 中实现预期结果的唯一方法吗?
解决方案
您可以尝试使所有Text
s 高度相同。为此,您需要明确设置填充和间距,因此这将缩放而不是固定的默认值。
此外,Spacer()
这里没有多大意义 - 如果要求所有内容Text
保持相同大小,Spacer
则只会使所有文本变小。对于Text
基于空间进行缩放,而在哪里Spacer
尝试使用尽可能多的空间,这是一个矛盾。相反,我决定只在初始化程序中设置VStack
's 。spacing
工作代码:
struct IndicatorExperiment: View {
private let size: CGFloat
private let padding: CGFloat
private let primarySpacing: CGFloat
private let secondarySpacing: CGFloat
private let textHeight: CGFloat
init(size: CGFloat) {
self.size = size
padding = size / 10
primarySpacing = size / 15
secondarySpacing = size / 40
let totalHeights = size - padding * 2 - primarySpacing * 2 - secondarySpacing
textHeight = totalHeights / 4
}
var body: some View {
VStack(spacing: primarySpacing) {
HStack {
scaledText("Line 1")
Spacer()
}
.frame(height: textHeight)
VStack(spacing: secondarySpacing) {
scaledText("Line 2")
scaledText("Line 3")
}
.frame(height: textHeight * 2 + secondarySpacing)
scaledText("Line 4")
}
.padding(padding)
.background(
RoundedRectangle(cornerRadius: 20)
.fill(Color.yellow)
)
.aspectRatio(1, contentMode: .fit)
.frame(width: size, height: size)
}
private func scaledText(_ content: String) -> some View {
Text(content)
.font(.system(size: 500))
.minimumScaleFactor(0.01)
.lineLimit(1)
.frame(height: textHeight)
}
}
测试代码:
struct ContentView: View {
var body: some View {
ScrollView {
VStack(spacing: 50) {
IndicatorExperiment(size: 100)
IndicatorExperiment(size: 200)
IndicatorExperiment(size: 300)
IndicatorExperiment(size: 400)
}
}
}
}
结果:
推荐阅读
- loops - Julia 中的命名循环
- php - Eloquent 模型在批量插入时触发保存事件
- python - 为什么我对二元分类最有用的特征的结果在 python 中总是相同的?
- python-3.x - 用户空闲时如何打开 Tkinter 窗口?
- typescript - 断言总是返回 err(期望 'a' 完全等于 'a')
- excel - 尝试根据标准将列中单元格的值移动到另一个
- azure - 无法让 Azure AD B2C 与 Xamarin Forms 一起使用
- kubernetes - Helm Chart 未正确部署
- python - Matplotlib 条件标记颜色
- cypher - CYPHER 获取节点之间的边