为什么GeometryReader不居中其子视图?

9

红边框是几何区域,黑边框是文本区域

目前正在使用 Xcode12 Beta 3 版本

struct Testing_Geometry_: View {
    var body: some View {
        GeometryReader { geo in
            Text("Hello, World!")
                .border(Color.black)
        }
        .border(Color.red)
    }
}

我想使用这段代码将文本居中定位。
struct Testing_Geometry_: View {
    var body: some View {
        GeometryReader { geo in
            Text("Hello, World!")
                .position(x:geo.frame(in:.global).midX,y:geo.frame(in:.global).midY)
                .border(Color.black)
        }
        .border(Color.red)
    }
}

但我得到的结果表明文本占用了整个几何空间,我认为这不正确!因为文本应该适合它们的空间。

对于布局系统,@twostraws建议采用三种角色:

1-父元素提供其尺寸

2-子元素选择其尺寸

3-父元素定位其子元素

但我认为这不正确!

文本正在占用整个几何空间


GeometryReader不是容器,因此没有默认对齐方式。我没看到你使用它,那么真正的问题在哪里? - Asperi
我刚刚尝试了你的代码,它为我居中显示了文本。你是怎么运行它的?用的是哪个版本的Xcode? - vacawama
我目前正在使用Xcode12 beta 3。 - amin torabi
3个回答

17

如果有人在寻找基础解决方案,您可以将其放置在一个栈中,并使其使用整个几何尺寸并居中对齐。这将使下面的所有元素都使用正确的大小并居中对齐。

GeometryReader { geometry in
    ZStack {
        // ... some of your views
    }
    .frame(width: geometry.size.width, height: geometry.size.height, alignment: .center)
}

1
问题在于修改器的顺序很重要,因为修改器实际上创建了父视图。我使用背景而不是边框,因为我认为背景更容易看到。请考虑以下代码,它与您的代码相同,只是使用了背景:
struct TestingGeometryView: View {
    var body: some View {
        GeometryReader { geo in
            Text("Hello, World!")
                .position(x:geo.frame(in:.global).midX,y:geo.frame(in:.global).midY)
                .background(Color.gray)
        }
        .background(Color.red)
    }
}

这将得到以下结果:

Xcode preview

从这里你会想,“文本占据了整个几何尺寸,我认为这不正确!”因为灰色背景占据了整个屏幕而不是仅围绕文本。再次强调,问题在于修改器的顺序-背景(或者在你的示例中是边框)是一个父视图,但是你将它作为“位置”视图的父级而不是文本视图的父级。为了使位置执行其功能,它需要利用整个可用的父空间(在本例中为整个屏幕减去安全区域)。因此,将背景或边框作为位置的父级意味着它们将占据整个屏幕。

让我们把顺序改成这样,这样背景视图只用于文本视图,我们就可以看到文本视图的大小:

struct TestingGeometryView: View {
    var body: some View {
        GeometryReader { geo in
            Text("Hello, World!")
                .background(Color.gray)
                .position(x:geo.frame(in:.global).midX,y:geo.frame(in:.global).midY)
        }
        .background(Color.red)
    }
}

这样做可以得到您期望的结果,文本视图只占用所需的最小空间,并遵循@twostraws所解释的规则。

Xcode preview as expected

这就是为什么修饰符的顺序非常重要。显然,GeometryReader视图占据整个屏幕,而Text视图只占用所需的空间。在您的示例中,Text视图仍然只占用所需的空间,但边框是围绕位置视图而不是Text视图。希望清楚明白 :-)

1
默认情况下: GeometryReader 将其子视图放置在左上角。 SwiftUI 视图将内容放置在其坐标空间的中心。 您可以使用 geo.frame(in: .global).midX 和 geo.frame(in: .global).midY 将元素居中。
struct TestingGeometryView: View {
    var body: some View {
        GeometryReader { geo in
            Text("Hello, World!")
                .background(Color.gray)
                .position(x: geo.frame(in: .global).midX, y: geo.frame(in: .global).midY)
        }
        .background(Color.red)
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接