SwiftUI Nested GeometryReader - 破坏 UI

Posted

技术标签:

【中文标题】SwiftUI Nested GeometryReader - 破坏 UI【英文标题】:SwiftUI Nested GeometryReader - Breaking UI 【发布时间】:2020-09-22 21:59:42 【问题描述】:

所以我想了解为什么我的子视图 (TopView) 会出现奇怪的大小调整问题。

这里是示例

import SwiftUI

struct ContentView: View 
    @State var isInterfaceHidden: Bool = false

    var body: some View 
        VStack(spacing: 0, content: 
            if !isInterfaceHidden 
                TopView()
                    .background(Color.yellow)
            
            Rectangle()
                .foregroundColor(Color.red)
                /// We make sure it won't cover the top and bottom view.
                .zIndex(-1)
            if !isInterfaceHidden 
                Rectangle()
                    .foregroundColor(Color.yellow)
                    .frame(height: 80)
            
        )
        .navigationBarTitle("")
        .navigationBarHidden(true)
    


struct TopView: View var body: some View 
        HStack(content: 
            VStack(spacing: 0, content: 
                Text("Text to show, it is a title.")
                    .tracking(0.2)
                    .foregroundColor(.white)
                    .lineLimit(1)
                GeometryReader(content:  geometry in
                    Text("Text to show, it is a subline.")
                        .tracking(0.2)
                        .foregroundColor(.white)
                        .lineLimit(1)
                )
                .background(Color.purple)
            )
        )
        .padding([.leading, .trailing], 20)
    

我尝试像这样设置.fixedSize()

GeometryReader(content:  geometry in
    Text("Text to show, it is a subline.")
        .tracking(0.2)
        .foregroundColor(.white)
        .lineLimit(1)
    )
    .background(Color.purple)

但它不完全适合文本,所以我不确定这是否是正确的解决方案。你们有什么想法吗?

【问题讨论】:

为什么在文本视图周围需要几何阅读器?我没有看到正在使用提供的几何图形。 我正在使用自定义文本,当文本大于可用宽度时,该文本会从右向左和从左向右滑动。如果需要,我也可以共享滑动文本组件。但我认为这里没有必要,因为无论有没有它都会破坏 UI。 您的自定义文本视图的工作方式是其高度取决于其宽度,我说得对吗?就像你有更长的文本一样——它以与标准 TextView 类似的方式分成多行。 是的,但是在这里,即使不使用自定义文本,它仍然会破坏我的 UI 以使 GeometryReader 的视图过大。 我明白这一点。 GeometryReader 的设计方式是尽可能多地占用空间。在这种情况下,通常有一种方法可以避免使用几何阅读器。使用您示例中的文本,解决方案是删除几何阅读器。但我想你真正的问题需要一个不同的解决方案。您的自定义视图的实现会有所帮助。另一种解决方案是使用锚点将高度从您的自定义视图发送回几何阅读器(这不会是美丽的 atm) 【参考方案1】:

请注意,从 14.0(2020 年 9 月 26 日)开始,GeometryReader 似乎出现了回归——或者可能是一种奇妙的未记录的行为变化——将布局权重向左上角——而不是中心。

这仅出现在我使用 XCode 12 开发和构建的应用程序中 - 在 ios 14 上运行的 XCode-11 编译应用程序没有出现此问题。网络上的大多数教程都假设这与它在 iOS 13/XCode 11 中的工作方式相同,并且您的代码可能会以不同的方式运行

iOS 14 has Changed (or broken?) SwiftUI GeometryReader 提出更多涉及相同问题的问题

【讨论】:

感谢您的解释,确实,我意识到 iOS 14 实际上是苹果在生产中发布的一个有缺陷的测试版? 对于这个例子,我指定了GeometryReader 的高度。 最新 XCode 12 中的行为发生了变化 - 请查看发行说明。他们……有点……记录他们。当然 - 实际技术文档中没有文档 - 因为谁读过正确的? 这太疯狂了?所以没有办法不强制geometryreader根据文本而不是逆来具有正常大小?【参考方案2】:

据我所知,GeometryReader 会将其父级的大小传回给父级,除非您将 frame() 明确设置为 GeometryReader。即便如此,如果您希望 GeometryReader 的区域适合 Text 视图(完全是您的自定义视图),则必须使用 preferenceanchorPreference 计算自定义视图的高度,然后将其设置为GeometryReader 的高度,以便让父级知道它需要分配的大小。

希望以下链接对您有所帮助。https://swiftui-lab.com/communicating-with-the-view-tree-part-1/

【讨论】:

谢谢!如果我找到解决方案,我会检查并回到这里! :) 所以我读了它,但它并没有真正解释为什么我的GeometryReader 在单独使用 Text 时不会破坏我的 UI。 swiftui-lab.com/geometryreader-to-the-rescue 这个最后解释了一点,GeometryReader 占用了所有可用空间,孩子会占用它需要的空间,但 GeometryReader 不会适应它。我不明白,因为 SwiftUI 应该给孩子空间并适应它周围的父母。而GeometryReader 打破了这个逻辑。 您的第一个屏幕截图看起来是第一个代码块的正确结果。但是,老实说,我不确切知道代码的哪一部分使它像第二个屏幕截图一样中断。特别是,我找不到您的代码中使用.fixedSize() 的位置,因此无法找出原因。你能分享更多破坏布局的代码吗? 这是完整的代码。我这里不用.fixedSize()【参考方案3】:

GeometryReader fit to View

如果您希望 GeometryReader 不会影响您的视图大小,您应该进行反转。您在 GeometryReader 中返回的视图应该是 out,GeometryReader 本身应该放在该视图的 backgroundoverlay 中。

Text("Text to show, it is a subline.")
    .tracking(0.2)
    .foregroundColor(.white)
    .lineLimit(1)
    .overlay(
        GeometryReader(content:  geometry -> Color in
            print(geometry.frame(in: .global))
            return Color.clear
        )
    )
    .background(Color.purple)

无论哪种方式(背景或叠加),都可以解决您的问题。尝试将overlay 更改为background 以查看。

只要记住返回一个Color.clear,这样GeometryReader 就变得不可见并且不会改变视图。

【讨论】:

以上是关于SwiftUI Nested GeometryReader - 破坏 UI的主要内容,如果未能解决你的问题,请参考以下文章

嵌套 JSON SwiftUI

nested friend

转:elasticsearch nested嵌套查询

Elasticsearch:运用 Java 对索引进行 nested 搜索

Elasticsearch:运用 Java 对索引进行 nested 搜索

[ElasticSearch]ES操作之嵌套查询(nested)与退出嵌套(reverse_nested)操作