简体   繁体   中英

Multiline UILabel - highlight certain range and truncate so that it is visible

I am currently working on a search functionality in one of my apps and I am stuck trying to resolve a very annoying issue.

Lets assume that I have the following 2 paragraphs of text:

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin commodo tristique lectus in blandit. Vivamus felis odio, laoreet in lorem eget, mattis imperdiet lorem.

Duis in nibh eleifend, lobortis mauris a, egestas odio.

When the user performs a search I will be displaying the results with a table view. The cells in this table view display 2 lines of text. In order to highlight the matching characters I am using attributed text and setting bold font for matching characters.

This all works well. However, I have one problem related to truncation. Lets suppose that the user searches for "egestas odio.". These words are located at the very end of the string, so, obviously, I would like to display the whole string and truncate its head.

Unfortunately, I cannot achieve this. Even though I set the correct truncation for NSMutableParagraphStyle which I am adding as an attribute of my attributed string, it doesn't work. I see the beginning of label with the tail being truncate instead of the head.

I have figured out that this problem is somewhat resolved if I remove all the newline characters. However, this is not very practical in my case.

Does someone know how I can overcome this obstacle? Alternatively, maybe you could give me some more general advise on how to implement the functionality that I need in a slightly different way. It seems fairly common and it is quite likely that there are some Open Source libraries which help to achieve this. Unfortunately, I couldn't find any so far.

Thanks in advance!

Given a string and a range you wanna keep, this walks in from either edge until the truncated string fits within a given size. You'll need to do additional work to recalculate the range within the truncated string.

Swift 4

func truncatedString(for text: String, with attributes: [NSAttributedStringKey: Any], constrainedTo size: CGSize, keeping range: Range<String.Index>?) -> String {

    let nsString = NSString(string: text)

    var nsRange = NSMakeRange(nsString.length / 2, 0)
    if let range = range {
        nsRange = NSRange(range, in: text)
    }

    var truncatedString = nsString

    let elipsis = "..."
    let elipsisWidth = elipsis.size(withAttributes: attributes).width

    var shouldAddFrontElipsis = false
    var shouldAddBackElipsis = false

    var constrainedWidthIncludingElipsis = size.width
    if nsRange.location > 0 {
        shouldAddFrontElipsis = true
        constrainedWidthIncludingElipsis -= elipsisWidth
    }

    if NSMaxRange(nsRange) < nsString.length {
        shouldAddBackElipsis = true
        constrainedWidthIncludingElipsis -= elipsisWidth
    }

    var startIndex = 0
    var endIndex = nsString.length

    while (truncatedString.boundingRect(with: CGSize(width: constrainedWidthIncludingElipsis, height: .greatestFiniteMagnitude), options: .usesLineFragmentOrigin, attributes: attributes, context: nil).size.height > size.height) {

        if startIndex == nsRange.location && endIndex == NSMaxRange(nsRange) {
            break
        } else {

            if startIndex < nsRange.location {
                startIndex += 1
            }

            if endIndex > NSMaxRange(nsRange) {
                endIndex -= 1
            }

            truncatedString = NSString(string: nsString.substring(with: NSMakeRange(startIndex, endIndex - startIndex)))
        }
    }

    if startIndex == 0 {
        shouldAddFrontElipsis = false
    }

    if endIndex == nsString.length {
        shouldAddBackElipsis = false
    }

    return (shouldAddFrontElipsis ? elipsis : "") + String(truncatedString) + (shouldAddBackElipsis ? elipsis : "")
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM