我想显示一个数学分数。为此,我有一个包含分子视图(称为ContainerView)、用作分数线的矩形和分母视图(与分子相同类型)的VStack。由于该分数是可编辑的,因此分子和分母的大小可能会发生变化,因此分数线必须相应地适应。我的第一次尝试是将分数线放在背景中,并使用几何读取器仅基于分子和分母的大小来获取分数的框架。这样,分数线位于背景的中心,大小也符合我的要求。以下是代码:
三个属性用于渲染分子和分母。结果就是这样。然而,由于它在背景中,它不知道分子和分母的高度。当它们大小不同时,会出现问题,就像在这种情况下。在图像中,您可以看到分子中有另一个分数,因此其视图的高度更大。这会导致一个问题,因为第一条分数线穿过了一部分分子。
为了避免这种情况,我认为最好的方法是直接将分数线放在主 VStack 中,这样它就可以在不考虑它们的高度的情况下划分分子和分母。但是,矩形形状占用了所有可用的空间,我不知道如何将其宽度限制为父级的宽度。这是新代码和它的样子:
总结一下,我需要找到一种方法来限制矩形的宽度,使其不超过没有该矩形时 VStack 的宽度。我尝试了使用偏好设置,按照this article的示例操作。
以下是我的尝试:
struct FractionView: View {
@EnvironmentObject var buffer: Buffer
var numeratorBufferIndex: Int
var denominatorBufferIndex: Int
var body: some View {
VStack(alignment: .center, spacing: 0) {
ContainerView(activeBufferIndex: numeratorBufferIndex)
.environmentObject(self.buffer)
ContainerView(activeBufferIndex: denominatorBufferIndex)
.environmentObject(self.buffer)
}
.background(GeometryReader { geometry in
Rectangle()
.frame(width: geometry.frame(in: .local).width, height: 2)
.foregroundColor(Color(.systemGray))
})
}
}
三个属性用于渲染分子和分母。结果就是这样。然而,由于它在背景中,它不知道分子和分母的高度。当它们大小不同时,会出现问题,就像在这种情况下。在图像中,您可以看到分子中有另一个分数,因此其视图的高度更大。这会导致一个问题,因为第一条分数线穿过了一部分分子。
为了避免这种情况,我认为最好的方法是直接将分数线放在主 VStack 中,这样它就可以在不考虑它们的高度的情况下划分分子和分母。但是,矩形形状占用了所有可用的空间,我不知道如何将其宽度限制为父级的宽度。这是新代码和它的样子:
struct FractionView: View {
@EnvironmentObject var buffer: Buffer
var numeratorBufferIndex: Int
var denominatorBufferIndex: Int
var body: some View {
VStack(alignment: .center, spacing: 0) {
ContainerView(activeBufferIndex: numeratorBufferIndex)
.environmentObject(self.buffer)
Rectangle()
.frame(height: 2)
.foregroundColor(Color(.systemGray))
ContainerView(activeBufferIndex: denominatorBufferIndex)
.environmentObject(self.buffer)
}
}
}
总结一下,我需要找到一种方法来限制矩形的宽度,使其不超过没有该矩形时 VStack 的宽度。我尝试了使用偏好设置,按照this article的示例操作。
以下是我的尝试:
struct FractionView: View {
@EnvironmentObject var buffer: Buffer
@State var fractionFrame: CGFloat = 0
var numeratorBufferIndex: Int
var denominatorBufferIndex: Int
var body: some View {
VStack(alignment: .center, spacing: 0) {
ContainerView(activeBufferIndex: numeratorBufferIndex)
.environmentObject(self.buffer)
Rectangle()
.frame(width: fractionFrame, height: 2)
.foregroundColor(Color(.systemGray))
ContainerView(activeBufferIndex: denominatorBufferIndex)
.environmentObject(self.buffer)
}
.coordinateSpace(name: "VStack")
.background(GeometryObteiner())
.onPreferenceChange(MyFractionPreferenceKey.self) { (value) in
print("Il valore della larghezza è \(value)")
self.fractionFrame = value
}
}
}
struct GeometryObteiner: View {
var body: some View {
GeometryReader { geometry in
Rectangle()
.frame(width: geometry.frame(in: .global).width, height: geometry.frame(in: .global).height)
.foregroundColor(.clear)
.preference(key: MyFractionPreferenceKey.self, value: geometry.frame(in: .named("VStack")).width)
}
}
}
struct MyFractionPreferenceKey: PreferenceKey {
typealias Value = CGFloat
static var defaultValue: CGFloat = 10
static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
value = nextValue()
}
}
然而,看起来onPreferenceChange从未被调用,因为result总是分数线具有默认值(10)的宽度。
也许解决方案比我想象的要简单得多,但我想不出来。我知道我写的可能有点令人困惑,如果您需要任何澄清,请在评论中向我提问。