How to have text in shapes in SwiftUI?
Asked Answered
I

6

37

I want to add text (eg. Hi) in a shape (eg. Square) in SwiftUI and make them act as a single object.

It looks like there's no direct way to add text in shape in SwiftUI.

Isabel answered 3/12, 2019 at 13:43 Comment(1)
I started with the solutions below, but ended up going with the view extension in this SO answer because it provided a little more flexibility in the corners you want rounded.Schober
N
40

Here is what I consider to be a more comprehensive answer. This will work as of Xcode 11.5:

Text(question)
    .fixedSize(horizontal: false, vertical: true)
    .multilineTextAlignment(.center)
    .padding()
    .frame(width: 300, height: 200)
    .background(Rectangle().fill(Color.white).shadow(radius: 3))

Notes:

  • fixedSize() will let the text wrap (since .lineLimit(nil) no longer is working). You can omit it if you simply want one line of text with ellipsis
  • multilineTextAlignment() allows you to center or align the text in any way
  • padding() gives the text more space to breathe within the Rectangle()
  • frame() sets the width and height of the Text() and hence, the Rectangle(), since it is the background of the Text()
  • background() sets the shape of the Text()'s background. I have added a fill color and a drop shadow here as well

The end result of this example is the text looks to appear within a cue card like shape!

Noisemaker answered 14/7, 2020 at 20:10 Comment(4)
I don't like this solution we shouldn't need to set the frame height/width... it should work with hugging and let the amount o text to stretch the view when neededSpangle
The original question stated "I want to add text (eg. Hi) in a shape (eg. Square)". You're not going to get a consistent shape unless you specify what that shape looks like, hence the use of frame() in this case.Noisemaker
Yes, I understand that, but in my opinion, what matters is not the height and width itself but the relation between height and width of 1:1 . This was previously achieved easily with a constraint height = width When working with different sizes/devices simultaneously this may cause some issues.Spangle
Well by that logic, if you just specify a relationship between height and width without specifying one of the aspects relative to the screen and pixel density, you will also have issues. If you take what is written as a starting point (which answers the question), you are free to enhance it to your needs.Noisemaker
P
29

Here is, IMO, most simple approach:

Generic schema

Text(_any_of_text_)
    .background(_any_of_Shape)

eg:

Text("Hello, World!")
    .background(Rectangle().stroke())

Text("Hello, World!")
    .background(RoundedRectangle(cornerRadius: 4).stroke())
Pelagi answered 3/12, 2019 at 16:11 Comment(1)
To add to this answer, you could also assign a .frame() property to the Text to specify an exact size for the Text/RectangleNoisemaker
R
23

Using Swift built-in shapes such as Capsule(), RoundedRectangle() and etc. Then, you can apply .overlay to the shape. The overlay take in any view such as text.

Example:

var body: some View {
    Capsule()
        .fill(Color.blue)
        .overlay(
            Text("Hello World")
        )
}

Outcome:

enter image description here

Rejuvenate answered 6/5, 2021 at 11:40 Comment(0)
R
2

Create a new SwiftUI View and make use of a Z-Stack to create your goal.

struct YourCustomObject: View {

    var body: some View {
        ZStack {
            Rectangle()
                .fill(Color.secondary)
                .frame(width: 200, height: 200)

            Text("Your desired text")
                .foregroundColor(.white)
        }
    }
}
Room answered 3/12, 2019 at 15:11 Comment(2)
This will not necessarily work as intended. If, say, the text is extremely long, it may bleed past the width or height of the rectangle's frame.Noisemaker
So how can we have a background aligned with the text no matter how much it has description in it ?Edie
M
2
Text("Hi")
 .frame(width: 40, height: 40, alignment: .center)
 .background(Color.black)
 .clipShape(Rectangle())
Marcoux answered 22/6, 2020 at 15:19 Comment(1)
This would be a better answer if you explained how the code you provided answers the question.Taal
I
0

Using ZStack you can, but the text might spill from the rectangle so you use

.offset()

E.g:

            ZStack {
                RoundedRectangle(cornerRadius: 11)
                    .stroke(Color("color5"), lineWidth: 1)
                    .frame(width: .infinity, height: 60)
               
                VStack(alignment: .leading) {
                    Text("Adewale")
                        .multilineTextAlignment(.leading)
                        .foregroundColor(Color("color5"))
                        .offset(x: -95 )
                }
            }

use the .offset() to tweak the location of the Text view on the RoundedRectangle view.

Interferometer answered 27/3, 2023 at 12:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.