19

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.

grg
  • 4,278
  • 3
  • 31
  • 43
AtharvSalokhe
  • 293
  • 1
  • 2
  • 11
  • I started with the solutions below, but ended up going with the view extension in this [SO answer](https://stackoverflow.com/a/58606176/9586164) because it provided a little more flexibility in the corners you want rounded. – Thomas Burke Dec 27 '21 at 20:06

5 Answers5

17

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!

Gene Loparco
  • 1,817
  • 19
  • 21
16

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())
Asperi
  • 173,274
  • 14
  • 284
  • 455
  • To add to this answer, you could also assign a .frame() property to the Text to specify an exact size for the Text/Rectangle – Gene Loparco Jul 14 '20 at 20:00
7

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

Swee Kwang
  • 268
  • 5
  • 10
2
Text("Hi")
 .frame(width: 40, height: 40, alignment: .center)
 .background(Color.black)
 .clipShape(Rectangle())
Christina
  • 21
  • 1
  • This would be a better answer if you explained how the code you provided answers the question. – pppery Jun 23 '20 at 00:25
1

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)
        }
    }
}
Tobias Hesselink
  • 1,269
  • 8
  • 15
  • 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. – Gene Loparco Jul 14 '20 at 19:54