11

How do you get the frame size in UIViewRepresentable?

I have a simple DrawView class that draw something and I would like to integrate with SwiftUI. This code works if I hardcode the frame size to 640x480, but is it possible to know the current frame size of ContentView?

struct ContentView: View {
    var body: some View {
        SwiftDrawView()
    }
}

struct SwiftDrawView: UIViewRepresentable {
    func makeUIView(context: Context) -> DrawView {
        DrawView(frame:CGRect(x: 0, y: 0, width: 640, height: 480))
    }
    ....
}

The Apple tutorial always use .zero and it won't work in this case.

Lim Thye Chean
  • 8,704
  • 9
  • 49
  • 88
  • 1
    Return a `.zero` frame from `makeUIView`, and try triggering the drawing in the `updateUIView` method of `UIViewRepresentable` – Matteo Pacini Jun 17 '19 at 06:29

2 Answers2

6
struct ContentView: View {
    var body: some View {
        GeometryReader { proxy in
            SwiftDrawView(frame: proxy.frame(in: .local))
        }
    }
}

struct SwiftDrawView: UIViewRepresentable {
    let frame: CGRect

    func makeUIView(context: Context) -> DrawView {
        DrawView(frame:frame)
    }
    ....
}
Julio Bailon
  • 3,735
  • 2
  • 33
  • 34
Victor Kushnerov
  • 3,706
  • 27
  • 56
4

The frame does not matter at UIView creation time (ie. in makeUIView), because constructed view will be resized according to final layout in container view and resulting frame will be passed in UIView.draw.

Here is complete example (Xcode 11.1) and Preview (Note: if you remove VStack in below example DrawView fills entire screen).

Drawing in UIViewRepresentable

import SwiftUI
import UIKit

class DrawView : UIView {
    override func draw(_ rect: CGRect) {
        let path = UIBezierPath(ovalIn: rect)
        UIColor.green.setFill()
        path.fill()
    }
}

struct SwiftDrawView: UIViewRepresentable {
    typealias UIViewType = DrawView

    func makeUIView(context: Context) -> DrawView {
        DrawView()
    }

    func updateUIView(_ uiView: DrawView, context: UIViewRepresentableContext<SwiftDrawView>) {
        // change here some DrawView properties if needed, eg. color
    }
}

struct ContentView: View {
    var body: some View {
        VStack {
            SwiftDrawView()
            Text("SwiftUI native")
        }
            .edgesIgnoringSafeArea(.all)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
Asperi
  • 228,894
  • 20
  • 464
  • 690