4

red border is geometry Area and black border is text area

currently using Xcode12 Beta 3

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

I wanted to position text in center with this code

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

but I got this result which means Text is taking the whole geometry size and I think it's not correct! cause texts has to fit in their space

three roles suggested by @twostraws for layout systems are

1- parent offers its size

2-child chooses its size

3-parent positions its child

but I think this isn't right!

text is taking the whole geometry space

amin torabi
  • 111
  • 1
  • 6

2 Answers2

6

If someone is looking for basic solution, you can put it in one of Stack and make it use whole size of geometry size with alignment center. That will make all elements underneath to use correct size and aligned in center

GeometryReader { geometry in
    ZStack {
        // ... some of your views
    }
    .frame(width: geometry.size.width, height: geometry.size.height, alignment: .center)
}
green0range
  • 387
  • 4
  • 16
1

The problem is that modifier order matters, because modifiers actually create parent views. I've used backgrounds instead of borders because I think they're easier to see. Consider this code that's the same as yours but just using a background:

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

This gives the following:

Xcode preview

From this you are thinking "Text is taking the whole geometry size and I think it's not correct!" because the gray background is taking the whole screen instead of just around the Text. Again, the problem is modifier order- the background (or border in your example) is a parent view, but you are making it the parent of the "position" view instead of the Text view. In order for position to do what it does, it takes the entire parent space available (in this case the whole screen minus safe area). So putting background or border as parent of position means they will take the entire screen.

Let's switch the order to this, so that background view is only for the Text view and we can see size of Text view:

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

This gives the result I think you were expecting with the Text view only taking up the minimum size required, and following those rules that @twostraws explained so nicely.

Xcode preview as expected

This is why modifier order is so important. It's clear that GeometryReader view is taking up the entire screen, and Text view is only taking up the space it requires. In your example, Text view was still only taking up the required space but your border was around the position view, not the Text view. Hope it's clear :-)

Jesse Pangburn
  • 505
  • 1
  • 4
  • 15