首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >SwiftUI中的拥抱子视图

SwiftUI中的拥抱子视图
EN

Stack Overflow用户
提问于 2019-06-30 06:08:56
回答 2查看 4.4K关注 0票数 13

Dave在他的关于自定义视图的SwiftUI讨论中解释了一些WWDC19布局的机制,但是他忽略了一些部分,我很难获得适当大小的视图。

是否有一种方法可以让视图告诉它的容器,它没有提出任何空间要求,但是它将使用它所提供的所有空间?另一种说法是容器应该拥抱其子视图。

具体的例子,我想要类似于c:

如果有一些TextVStack中,如a),则VStack将采用它的宽度到最宽的子视图。

如果您像在b中一样添加一个Rectangle,它将尽可能地展开,直到VStack填充它的容器为止。

这表明Texts和Rectangles在布局上属于不同的类别,Text有固定的大小,而Rectangle是贪婪的。但是,如果我要制作自己的View**?**,如何与容器进行通信呢?

我真正想要达到的结果是( c)。当VStack确定它的大小时,它应该忽略矩形(或我的自定义视图),然后一旦它这样做了,它应该告诉矩形,或者我的自定义视图,它可以有多少空间。

考虑到SwiftUI似乎是自下而上的布局,也许这是不可能的,但似乎应该有some的方法来实现这一点。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-06-30 06:52:32

没有修饰符(AFAIK)来完成这一任务,所以我的方法如下。如果这是您要经常使用的东西,那么创建您自己的修饰符可能是值得的。

还请注意,这里我使用的是标准首选项,但锚首选项甚至更好。这是一个很难解释的话题。我写了一篇文章,你可以在这里查看:https://swiftui-lab.com/communicating-with-the-view-tree-part-1/

您可以使用下面的代码来完成您想要的任务。

代码语言:javascript
代码运行次数:0
运行
复制
import SwiftUI

struct MyRectPreference: PreferenceKey {
    typealias Value = [CGRect]

    static var defaultValue: [CGRect] = []

    static func reduce(value: inout [CGRect], nextValue: () -> [CGRect]) {
        value.append(contentsOf: nextValue())
    }
}

struct ContentView : View {
    @State private var widestText: CGFloat = 0

    var body: some View {
        VStack {
            Text("Hello").background(RectGetter())
            Text("Wonderful World!").background(RectGetter())
            Rectangle().fill(Color.blue).frame(width: widestText, height: 30)
            }.onPreferenceChange(MyRectPreference.self, perform: { prefs in
                for p in prefs {
                    self.widestText = max(self.widestText, p.size.width)
                }
            })
    }
}

struct RectGetter: View {

    var body: some View {
        GeometryReader { geometry in
            Rectangle()
                .fill(Color.clear)
                .preference(key: MyRectPreference.self, value: [geometry.frame(in: .global)])
        }
    }
}
票数 8
EN

Stack Overflow用户

发布于 2019-07-02 11:26:22

所以我找到了一种方法。首先,我试着用不同的配置在视图周围放置垫片,试图把它推到一起,但那是行不通的。然后,我意识到我也许可以使用.background修饰符,这确实奏效了。它似乎让拥有的视图首先计算它的大小,然后就把它作为它的框架,这正是我想要的。

这只是一个例子,一些黑客,以获得正确的高度,但这是一个小细节,在我的特殊用例是不需要的。如果你够聪明的话,可能也不在这里。

代码语言:javascript
代码运行次数:0
运行
复制
var body: some View {
    VStack(spacing: 10) {
        Text("Short").background(Color.green)
        Text("A longer text").background(Color.green)
        Text("Dummy").opacity(0)
    }
    .background(backgroundView)
    .background(Color.red)
    .padding()
    .background(Color.blue)
}

var backgroundView: some View {
    VStack(spacing: 10) {
        Spacer()
        Spacer()
        Rectangle().fill(Color.yellow)
    }
}

蓝色的视图和所有的颜色背景,当然只是为了让它更容易看到。此代码生成以下内容:

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56822791

复制
相关文章

相似问题

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