1

I am porting and old Objective C application where I used attributed string to write text in - (void)drawRect:(CGRect)rect.

I am not able to draw text using the SwiftUI Path though. I found a similar question without any answer (Mac OS X - SwiftUI - how to draw a String (text) together with some path )

Let suppose that I need to write a label over an horizontal line in the middle of the screen.

Using the following code, the line shows up in the expected position. Text doesn't show up, instead.

struct TestView: View {
    var body: some View {
        GeometryReader { geometry in
            contentView(geometry: geometry)
        }
    }

    func contentView(geometry: GeometryProxy) -> some View {
        let content = VStack {
            ZStack {
                LineAndText()
                    .stroke()
            }
        }
        return content
    }
}

struct LineAndText: Shape {
    func path(in rect: CGRect) -> Path {
        Path { path in
            path.move(to: CGPoint(x: 0, y: rect.size.height / 2))
            path.addLine(to: CGPoint(x: rect.width, y: rect.size.height / 2))
            
            let label = "label"
            label.draw(at: CGPoint(x:0, y:rect.size.height / 2))
        }
    }
}

How do I write text in the desired position?

NOTE: The real scenario is much more complex, I have many lines with different vertical and horizontal labels so I need to control the label position at pixel level.

Fab
  • 1,468
  • 1
  • 16
  • 37
  • Does this answer your question https://stackoverflow.com/a/60888570/12299030? – Asperi Oct 20 '20 at 11:08
  • Unfortunately, it doesn't. As I mentioned in my question, I need to control the text position at pixel level. – Fab Oct 20 '20 at 11:54
  • "I need to control the label position at pixel level" can be a very complex problem (hundreds of lines of code, over a week to develop the last time I did this), or fairly straightforward (one quick View), depending on exactly the layout you're looking for. In particular, do you know the locations of everything in advance, or do you need to adjust positions based on the size of the text? When you say "vertical and horizontal labels," do you mean that the text is rotated (and that the layout needs to be based on the rotated size)? – Rob Napier Oct 20 '20 at 13:25
  • 1
    The starting point for this is to get rid of `.draw(at:)`. That means nothing at all in SwiftUI (it requires an existing UIGraphicsContext). What you want is a ZStack with a Path and a Text. Correctly placing the Text is the challenge, and depends on how flexible you need it to be. But as a starting point, you can try setting your ZStack to `alignment: .topLeading` and then using `.offset` to place the text where you think it should go. (If this sounds like a workable approach, but you have trouble writing it, I can write up an answer around that.) – Rob Napier Oct 20 '20 at 13:29
  • @Napier. Thank you for your answer. Basically I have to calculate the labels locations based on received data. Labels may be rotated of 90 degrees. Anyway, I got to the same solution you are proposing (ZStack and .offset). I think that it is quite weird and I actually doesn't like it. Maybe because I have been working for years with UIKit where drawing and positioning text can be done at the same time. – Fab Oct 20 '20 at 17:42

0 Answers0