gpt4 book ai didi

ios - 在 SwiftUI 中将形状设为父 View 的大小

转载 作者:行者123 更新时间:2023-11-29 13:51:36 25 4
gpt4 key购买 nike

我想显示一个数学分数。为此,我有一个 VStack,其中包含分 subview (称为 ContainerView)、一个用作分数线的矩形和一个分母 View (相同类型的分子)。由于分数是可编辑的,分子和分母的大小可以改变,分数线必须随之调整。我的第一次尝试是将分数线放在背景中,并使用几何阅读器仅根据分子和分母的大小来获取分数的框架。通过这种方式,分数线位于背景的中心,具有我想要的大小。这是代码:

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))
})
}
}

这三个属性用来渲染分子和分母。 The result is this .但是,由于它在后台,因此它不知道分子和分母的高度。当它们有不同的尺寸时,这会产生问题,like in this case .在图像中,您可以看到分子中有另一个分数,因此它的 View 高度更大。这会导致问题,因为第一条分数线穿过分子的一部分。

为了避免这种情况,我认为最好的方法是将分数线直接放在主 VStack 中,这样它就可以在不关心分子和分母的高度的情况下划分它们。然而,矩形占用了所有可用空间,我不知道如何将其宽度限制为父级的宽度。这是新代码和what it looks like :

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()
}
}

然而,自从 result 以来,似乎从未调用过 onPreferenceChange始终是分数线具有默认值 (10) 的宽度。

也许解决方案比我想象的要容易得多,但我想不通。我知道我写的内容可能有点困惑,如果您需要任何说明,请在评论中问我。

最佳答案

这里应用了与您的场景评论相同的想法。当然它只是草图,但 IMO 可以根据需要对其进行调整并使其通用(将当前使用的 Text 替换为 ViewFullFraction 本身来构造更复杂的分数)。

演示(因为 DispatchQueue 用于避免在 View 绘制警告期间修改,您应该运行它以查看结果):

SwiftUI math fraction

代码(截图演示):

struct FullFraction: View {
var whole: String = ""
var num: String
var denom: String

@State private var numWidth: CGFloat = 12.0 // just initial
@State private var denomWidth: CGFloat = 12.0 // just initial
var body: some View {
HStack {
Text(whole)
VStack {
numerator
divider
denominator
}
}
}
var numerator: some View {
Text(num)
.offset(x: 0, y: 8)
.alignmentGuide(HorizontalAlignment.center, computeValue: { d in
DispatchQueue.main.async {
self.numWidth = d.width
}
return d[HorizontalAlignment.center]
})
}
var denominator: some View {
Text(denom)
.offset(x: 0, y: -4)
.alignmentGuide(HorizontalAlignment.center, computeValue: { d in
DispatchQueue.main.async {
self.denomWidth = d.width
}
return d[HorizontalAlignment.center]
})
}

var divider: some View {
Rectangle().fill(Color.black).frame(width:max(self.numWidth, self.denomWidth), height: 2.0)
}
}

struct DemoFraction: View {
var body: some View {
VStack {
FullFraction(whole: "F", num: "(a + b)", denom: "c")
Divider()
FullFraction(whole: "ab12", num: "13", denom: "761")
Divider()
FullFraction(num: "1111", denom: "3")
}
}
}

关于ios - 在 SwiftUI 中将形状设为父 View 的大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59445483/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com