Search code examples
iosswiftimagetextswiftui

Wrap Text Around a Variable Amount of Images in SwiftUI


Wondering if anyone has any ideas about having a Text component wrap a variable amount of Image components at the beginning of a line 🤔. What I'm looking to accomplish is something like this:

enter image description here

where all rows of text after the first should wrap inline underneath that image, and there could be multiple images at the beginning of the line (let's say a max of 3). This is the code I currently have:

var body: some View {
  VStack {
    HStack(alignment: .center) {
      BadgeImage(from: debugUrl)
      Text("\(Text(message.user).foregroundColor(message.color)): \(message.text)")
    }
    Spacer()
  }
  .padding(.horizontal, 10)
}

where BadgeImage is just a wrapper for SwiftUI's AsyncImage that simply handles the URL object creation (ignore the VStack and Spacer just there for the picture).

I know we can interpolate an Image into Text with SwiftUI, but this doesn't help since the number of images is variable and has to be fetched from a URL, so I have to use AsyncImage. Manually implementing the async logic leaves me having to then do something like Text("\(someStateVar) some text..."), but seems like Swift only allows image interpolation at build time and using a state var leaves me with the string description of an image instead of the actual Image component within the text.

🤔

The core question is: is there a way to implement Text wrapping with a variable amount of some View components at the beginning of a line, or does this have to be manually implemented with something like CoreText?


Solution

  • Thanks to @Fogmeister for the tip! Went with just doing Text(someImageVar) + Text("The text...) and this works great. I've now just got something like this:

    var body: some View {
      HStack(alignment: .bottom) {
        content
      }
      .padding(.horizontal, 10)
      .padding(.vertical, 1)
      .onAppear(perform: onAppear)
    }
    

    And the onAppear logic just runs an async Task and ends up doing content = content + Text(newlyLoadedImage)