How to fill rect beneath Text inside Canvas in SwiftUI

134 Views Asked by At

I'm trying to draw text with a filled and inset rectangle under the text that matches the text's size inside a Canvas in SwiftUI, but I'm unable to figure out how to get the dimensions of the Text view.

struct ContentView: View {
    var body : some View {
        Canvas { context,size in
            let TEXT = Text("Some text").foregroundColor(.black)
//            context.fill(TEXT.boundingRect.insetBy(dx: -4, dy: -2), with: .color(.red)) // error: no boundingRect
            context.draw(TEXT, at: CGPoint(x: size.width/2,y: size.height/2))
        }
    }
}
1

There are 1 best solutions below

1
rob mayoff On BEST ANSWER

You need ask the GraphicsContext to ‘resolve’ the Text. You can then ask the ResolvedText to measure itself.

struct ContentView: View {
  var body: some View {
    Canvas { gc, size in
      let text: Text = Text("some text")
        .foregroundColor(.black)
      let resolvedText = gc.resolve(text)

      let textSize = resolvedText.measure(in: size)
      let textRect = CGRect(
        x: 0.5 * (size.width - textSize.width),
        y: 0.5 * (size.height - textSize.height),
        width: textSize.width,
        height: textSize.height
      )

      let bgRect = textRect.insetBy(dx: -5, dy: -5)
      gc.fill(Path(bgRect), with: .color(.mint))

      gc.draw(resolvedText, in: textRect)
    }
  }
}

Output:

black text on a mint rectangle

I found that I needed to make the type of the text variable explicit (let text: Text). Otherwise, the compiler infers type some View, which can't be resolved.