iosiphoneswiftuiword-wraprectangles

How to Create a Rectangle in SwiftUI that Extends width According to the Number of Lines of Text within, swiftui (Similar to Wrap Content in uikit)


working on a SwiftUI project where I need a blue rectangle to adjust its ** width** based on the number of lines of text it contains, specifically not dynamically, but based on a fixed number of lines (e.g., 2 lines, 4 lines, etc.).

struct ContentView: View {
    var body: some View {
        ZStack {
            // Background rectangle with corner radius - Top rectangle is here only for the shadow
            Rectangle()
                .fill(Color.green)
                .frame(width: 200 - 24, height: 20) // Width adjusted for padding
                .padding(12) // Use half of the padding to align properly
                .shadow(color: .gray, radius: 24, x: 0, y: 100) // Shadow for the top rectangle
                .fixedSize(horizontal: true, vertical: false)
                .padding()
            
            Rectangle()
                .fill(Color.blue)
                .frame(width: 200, height: 200)
                .cornerRadius(20) // Apply corner radius
            
            // Text inside the blue rectangle
            Text("This is some text")
                .foregroundColor(.white) // Text color
                .multilineTextAlignment(.center) // Center align text
                .padding() // Padding inside the rectangle
                .frame(maxWidth: .infinity, maxHeight: .infinity) // Allow text to occupy full space
        }
        .padding(20) // Padding for the ZStack
    }
}

!The rectangle should expand to accommodate the number of lines of text until it reaches the edge of the screen]1


Solution

  • I was asking in a comment, how the width of the rectangle is supposed to be determined by the number of lines? I would expect, the number of lines will determine the height.

    Anyway, maybe you can get the effect you want by applying the blue rectangle as .background to the Text, instead of using a ZStack.

    Something like this:

    struct ContentView: View {
        let theQuickBrownFox = "The quick brown fox jumps over the lazy dog"
        var body: some View {
            Text(theQuickBrownFox) // "This is some text"
                .foregroundStyle(.white)
                .multilineTextAlignment(.center)
                .padding()
                .frame(minWidth: 200, minHeight: 200)
                .background {
                    RoundedRectangle(cornerRadius: 20)
                        .fill(.blue)
                }
                .background(alignment: .bottom) {
                    Color.blue
                        .frame(height: 20)
                        .padding(.horizontal, 12)
                        .padding(.bottom, 20)
                        .shadow(color: .gray, radius: 24, x: 0, y: 30)
                }
                .padding(20)
        }
    }
    

    Screenshot