swiftui

How to get size of child?


Is there any way to get the size of a child view in SwiftUI?

I'm basically looking to do the UIKit equivalent of:

self.child.frame.origin.x -= self.child.intrinsicContentSize.width/2.0

I don't think a GeometryReader would work since that returns the available size in the parent.

[Edit] I've found it's possible to get and save the dimensions using .alignmentGuide(_, computeValue:) though that's definitely a hack.

LessonSliderText(text: self.textForProgress(self.progress), color: self.completedColor)
    .alignmentGuide(HorizontalAlignment.leading) { (dimensions) -> Length in
        self.textSize = CGSize(width: dimensions.width, height: dimensions.height)
        return 0
    }
    .offset(x: self.width*self.currentPercentage - self.textSize.width / 2.0)
    .offset(y: -self.textSize.height/2.0)
    .animation(nil)
    .opacity(self.isDragging ? 1.0 : 0.0)
    .animation(.basic())

What I'm trying to accomplish


Solution

  • Basically, the answer at this point is to use a GeometryReader inside of the child's background(...) modifier.

    // This won't be valid until the first layout pass is complete
    @State var childSize: CGSize = .zero
    
    var body: some View {
        ZStack {
            Text("Hello World!")
                .background(
                    GeometryReader { proxy in
                        Color.clear
                           .preference(
                               key: SizePreferenceKey.self, 
                               value: proxy.size
                            )
                    }
                )
          }
          .onPreferenceChange(SizePreferenceKey.self) { preferences in
              self.childSize = preferences
          }
    }
    
    struct SizePreferenceKey: PreferenceKey {
        typealias Value = CGSize
        static var defaultValue: Value = .zero
    
        static func reduce(value: inout Value, nextValue: () -> Value) {
            value = nextValue()
        }
    }