首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在SwiftUI中创建与父视图大小相同的形状

在SwiftUI中创建与父视图大小相同的形状
EN

Stack Overflow用户
提问于 2019-12-22 23:19:58
回答 1查看 2K关注 0票数 3

我想展示一个数学分数。为此,我有一个包含分子视图(称为ContainerView)的VStack、一个用作分数线的矩形和一个分母视图(与分子的类型相同)。由于分数是可编辑的,分子和分母的大小可以改变,因此分数线必须相应地进行调整。我的第一个尝试是将分数线放在背景中,并使用几何阅读器仅根据分子和分母的大小获得分数的框架。这样,分数线就在背景的中心,大小和我想要的一样大。代码如下:

代码语言:javascript
复制
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。在图像中,您可以看到分子中有另一个分数,因此其视图的高度较大。这会导致问题,因为第一个分数线通过分子的一部分。

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

代码语言:javascript
复制
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的例子使用首选项。这就是我尝试过的

代码语言:javascript
复制
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)的宽度。

也许解决方案比我想的要简单得多,但我想不出来。我知道我写的东西可能有点混乱,如果你需要任何澄清,请在评论中问我。提前谢谢。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-12-23 15:40:52

这里应用了与您的场景注释相同的想法。当然,它只是很粗糙,但可以根据需要进行调整,并使其成为通用的(例如,用ViewFullFraction本身替换当前使用的Text,以构造更复杂的分数)。

Demo (因为DispatchQueue是为了避免视图绘制过程中的修改,所以你应该运行它才能看到结果):

截图demo代码:

代码语言:javascript
复制
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")
        }
    }
}

struct DemoFraction_Previews: PreviewProvider {
    static var previews: some View {
        DemoFraction()
    }
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59445483

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档