admin管理员组

文章数量:1392116

In my project, I am getting some text from backend which could have html tags. For this, I am converting the string to attributed string. However I noticed that when the string has html tags with color in it and when the text is displayed in toolbar, then the text displays with an ellipsis towards the end. Sharing code below:

import SwiftUI

struct ContentViewA: View {
    @State private var displayText: AttributedString?
    
    var body: some View {
        NavigationStack {
            VStack {
                Text(displayText ?? "")
            }
            .toolbar {
                ToolbarItem(placement: .cancellationAction) {
                    Button {
                    } label: {
                        Text("Done").font(.body.bold())
                    }
                }
                
                ToolbarItem(placement: .principal) {
                    Text(displayText ?? "")
                }
            }
            .onAppear {
                let string = "<div><p><span style=\"color:#FF0000;\">Hello World</span></p></div>"
                displayText = string.convertToAttributedString
                /// Note: If I don't set the font, then the ellipsis are not displayed in the toolbar, but I need this font style.
                displayText?.font = .body.bold()
            }
        }

    }
}

extension String {
    var convertToAttributedString: AttributedString? {
        guard let data = data(using: .utf8) else { return nil }
        var attributedString: AttributedString?
        if let nsAttributedString = try? NSAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html,
                                                                                  .characterEncoding: String.Encoding.utf8.rawValue],
                                                            documentAttributes: nil) {
            attributedString = try? AttributedString(nsAttributedString, including: \.uiKit)
        }
        
        return attributedString
    }
}

I am printing displayText in the body of the view and am not seeing ellipsis at the end of the string, but in toolbar, I am seeing ellipsis. I am unable to figure out what's causing this and what can be the fix for it. However, if I avoid setting the font on attributed string, then the ellipsis are not displayed in toolbar. However, I need to set the string to a specific font style.

How can I avoid ellipsis in toolbar and while also setting the required font on the string?

Sharing screenshot, if needed:

Edit: Based on Benzy Neez's comment, I applied fixedSize modifier to the text view. It does fix the issue, but also moves the title to vertically top and it then doesn't horizontally align with 'Done' button.

In my project, I am getting some text from backend which could have html tags. For this, I am converting the string to attributed string. However I noticed that when the string has html tags with color in it and when the text is displayed in toolbar, then the text displays with an ellipsis towards the end. Sharing code below:

import SwiftUI

struct ContentViewA: View {
    @State private var displayText: AttributedString?
    
    var body: some View {
        NavigationStack {
            VStack {
                Text(displayText ?? "")
            }
            .toolbar {
                ToolbarItem(placement: .cancellationAction) {
                    Button {
                    } label: {
                        Text("Done").font(.body.bold())
                    }
                }
                
                ToolbarItem(placement: .principal) {
                    Text(displayText ?? "")
                }
            }
            .onAppear {
                let string = "<div><p><span style=\"color:#FF0000;\">Hello World</span></p></div>"
                displayText = string.convertToAttributedString
                /// Note: If I don't set the font, then the ellipsis are not displayed in the toolbar, but I need this font style.
                displayText?.font = .body.bold()
            }
        }

    }
}

extension String {
    var convertToAttributedString: AttributedString? {
        guard let data = data(using: .utf8) else { return nil }
        var attributedString: AttributedString?
        if let nsAttributedString = try? NSAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html,
                                                                                  .characterEncoding: String.Encoding.utf8.rawValue],
                                                            documentAttributes: nil) {
            attributedString = try? AttributedString(nsAttributedString, including: \.uiKit)
        }
        
        return attributedString
    }
}

I am printing displayText in the body of the view and am not seeing ellipsis at the end of the string, but in toolbar, I am seeing ellipsis. I am unable to figure out what's causing this and what can be the fix for it. However, if I avoid setting the font on attributed string, then the ellipsis are not displayed in toolbar. However, I need to set the string to a specific font style.

How can I avoid ellipsis in toolbar and while also setting the required font on the string?

Sharing screenshot, if needed:

Edit: Based on Benzy Neez's comment, I applied fixedSize modifier to the text view. It does fix the issue, but also moves the title to vertically top and it then doesn't horizontally align with 'Done' button.

Share Improve this question edited Mar 11 at 18:30 tech_human asked Mar 11 at 17:26 tech_humantech_human 7,17617 gold badges76 silver badges135 bronze badges 4
  • Your example works for me when running on an iPhone 16 simulator with iOS 18.2. I also tried a much longer string, which wrapped to 2 lines instead of being truncated. Anyway, try applying .fixedSize() to the Text in the ToolbarItem. – Benzy Neez Commented Mar 11 at 17:46
  • FixedSize does kind of fix the issue i.e. the ellipsis does not get displayed in the toolbar, but the placement of the header moves up top i.e. it's not horizontally aligned to 'Done' button if I add fixedSize to the toolbar title. – tech_human Commented Mar 11 at 18:09
  • 1 The vertical alignment is probably caused by the HTML text being nested inside <div><p>. Do you have to live with this, or can you strip them away? – Benzy Neez Commented Mar 11 at 19:03
  • I can strip them away, but my string won't always have same html tags or most of times it will not even have any tags at all. alignment guide seems like the best solution in this case. – tech_human Commented Mar 11 at 19:56
Add a comment  | 

1 Answer 1

Reset to default 1

Following up from the comments... the truncation can be prevented by applying .fixedSize() to the Text in the ToolbarItem:

ToolbarItem(placement: .principal) {
    Text(displayText ?? "")
        .fixedSize()
}

However, when you try this, the text is no longer aligned with the "Done" button:

The reason why the text is mis-aligned is because the text is contained in a block with a blank line. You can see this by adding a border around the text:

Text(displayText ?? "")
    .fixedSize()
    .border(.red)

The block and the blank line are being caused by the HTML tags <div><p>, which are surrounding the styled text.

Here are two ways to fix:

1. Remove the HTML nesting

let string = "<span style=\"color:#FF0000;\">Hello World</span>"

2. Add an .alignmentGuide modifier

Alternatively, if the HTML stays unchanged, an alignment guide can be used to shift the block down by half its height:

Text(displayText ?? "")
    .fixedSize()
    .alignmentGuide(VerticalAlignment.center) { dimensions in
        -dimensions.height / 2
    }

Both methods give the same result:

本文标签: swiftEllipsis getting added in the toolbar text when font is set on attributed stringStack Overflow