Border around every word of UILabel

后端 未结 4 584
天命终不由人
天命终不由人 2021-01-07 09:06

Is there a way i can draw border around every word of UILabel. Suppose UILabel contains the string \" This is the Line 1\".

I want 5 differ

相关标签:
4条回答
  • 2021-01-07 09:40

    SWIFT 4 Version

    This is the swift 4 version of vikingosegundo Answer using a UITextView including a few other tweaks including:
    • list of words coming from an array
    • Centering in the textView
    • Adjustable word limit
    • Custom font

    //: Playground - noun: a place where people can play
    
    import UIKit
    
    var array = [String]()
    
    array = ["WORD1", "WORD2", "WORD3", "WORD4", "WORD4", "LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONGWORD", "WORD5"]
    
    var stringarr = String()
    
    for i in 0...(array.count-1) {
    
    if array[i].count > 20 {
        let count = array[i].count
        let dropCount = count-20
        let dropCharacters = array[i].dropLast(dropCount)
        var shortenedWord = "\(dropCharacters)"
        shortenedWord = "\(shortenedWord)..."
        print(shortenedWord)
        array[i] = shortenedWord
    
        }
    }
    
    stringarr = array.joined(separator: " ")
    
    
    func frameOfTextInRange(range:NSRange, inTextView textView:UITextView) -> CGRect {
        let beginning = textView.beginningOfDocument
        let start = textView.position(from: beginning, offset: range.location)
        let end = textView.position(from: start!, offset: range.length)
        let textRange = textView.textRange(from: start!, to: end!)
        let rect = textView.firstRect(for: textRange!)
    
        return textView.convert(rect, from: textView)
    }
    
    let textView = UITextView(frame: CGRect(x: 0, y: 0, width: 375, height: 200))
    textView.backgroundColor = UIColor.clear
    
    let lineSpacing: CGFloat = 0.0
    
    textView.attributedText = {
        let attributedString = NSMutableAttributedString(string: stringarr)
        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.lineHeightMultiple = 1.5
        paragraphStyle.lineSpacing = lineSpacing
        attributedString.addAttribute(.paragraphStyle, value: paragraphStyle, range: NSRange(location: 0, length: stringarr.count))
        attributedString.addAttribute(.foregroundColor, value: UIColor.white, range: NSRange(location: 0, length: stringarr.count))
        attributedString.addAttribute(.font, value: UIFont(name: "AvenirNext-Regular", size: 10.0)!, range: NSRange(location: 0, length: stringarr.count))
    
    
    let regex = try! NSRegularExpression(pattern: "\\s", options: [])
    let matches = regex.matches(in: stringarr, options: [], range: NSRange(location: 0, length: stringarr.count))
    
    for m in matches {
        attributedString.addAttribute(.kern, value: 6, range: m.range)
    }
    
    return NSAttributedString(attributedString: attributedString)
    }()
    
    
    textView.textAlignment = .center
    
    let textViewBG = UIView(frame: textView.bounds)
    textViewBG.backgroundColor = UIColor.white
    
    let pattern = "[^ ]+"
    let regex = try! NSRegularExpression(pattern: pattern, options: [])
     let matches = regex.matches(in: stringarr, options: [], range: NSRange(location: 0, length: stringarr.count))
    
    for m in matches {
    textViewBG.addSubview({
        let range = m.range
        let frame = frameOfTextInRange(range: range, inTextView: textView).insetBy(dx: CGFloat(-2), dy: CGFloat(3)).offsetBy(dx: CGFloat(0), dy: CGFloat(3))
        let v = UIView(frame: frame)
        v.layer.cornerRadius = 0
        v.backgroundColor = UIColor.black
        return v
        }())
    }
    
    textViewBG.addSubview(textView)
    
    //: End of playground
    



    Result

    Hope that helps!

    0 讨论(0)
  • 2021-01-07 09:48

    I am not aware of an easy to use code for UILabel, but for UITextView:

    Swift playground

    setup:

    import UIKit
    
    let string = "Lorem ipsum dolor sit amet"
    
    let textView = UITextView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
    textView.text = string
    

    use regular expressions get a match for every word:

    let pattern = "[a-zA-Z0-9]+"
    let regex = try! NSRegularExpression(pattern: pattern, options: [])
    let matches = regex.matchesInString(string, options: [], range: NSMakeRange(0, string.characters.count))
    

    function to get a rect for each match (ported from this answer):

    func frameOfTextInRange(range:NSRange, inTextView textView:UITextView) -> CGRect {
        let beginning = textView.beginningOfDocument
        let start = textView.positionFromPosition(beginning, offset: range.location)!
        let end = textView.positionFromPosition(start, offset: range.length)!
        let textRange = textView.textRangeFromPosition(start, toPosition: end)!
        let rect = textView.firstRectForRange(textRange)
        return textView.convertRect(rect, fromView: textView)
    }
    

    iterate over each match, get its frame, use it to create a view for the background, add it to the text view:

    for m in matches {
        let range = m.range
        let frame = frameOfTextInRange(range, inTextView: textView)
        let v = UIView(frame: frame)
        v.layer.borderWidth = 1
        v.layer.borderColor = UIColor.blueColor().CGColor
        textView.addSubview(v)
    
    }
    


    But possibly this doesn't give the result you were expecting. To get a better controls, you could use attributed strings.

    Here the same code with using attributed strings

    import UIKit
    
    let string = "Lorem ipsum dolor sit amet"
    
    let textView = UITextView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
    
    let attributedString = NSMutableAttributedString(string: string)
    let paragraphStyle = NSMutableParagraphStyle()
    paragraphStyle.lineHeightMultiple = 1.25
    attributedString.addAttribute(NSParagraphStyleAttributeName, value: paragraphStyle, range: NSMakeRange(0, string.characters.count))
    
    textView.attributedText = attributedString
    
    let pattern = "[a-zA-Z0-9]+"
    let regex = try! NSRegularExpression(pattern: pattern, options: [])
    let matches = regex.matchesInString(string, options: [], range: NSMakeRange(0, string.characters.count))
    
    func frameOfTextInRange(range:NSRange, inTextView textView:UITextView) -> CGRect {
        let beginning = textView.beginningOfDocument
        let start = textView.positionFromPosition(beginning, offset: range.location)!
        let end = textView.positionFromPosition(start, offset: range.length)!
        let textRange = textView.textRangeFromPosition(start, toPosition: end)!
        let rect = textView.firstRectForRange(textRange)
        return textView.convertRect(rect, fromView: textView)
    }
    
    for m in matches {
        let range = m.range
        var frame = frameOfTextInRange(range, inTextView: textView)
        frame = CGRectInset(frame, CGFloat(-1.2), CGFloat(2))
        frame = CGRectOffset(frame, CGFloat(0), CGFloat(2))
        let v = UIView(frame: frame)
        v.layer.borderWidth = 1
        v.layer.borderColor = UIColor.blueColor().CGColor
        textView.addSubview(v)
    
    }
    


    Also helpful to create beautiful styles would be to add the views to a background view and add that textview on top

    import UIKit
    
    let string = "Lorem ipsum dolor sit amet"
    
    let textView = UITextView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
    let textViewBG = UIView(frame: textView.bounds)
    textViewBG.backgroundColor = UIColor.whiteColor()
    let attributedString = NSMutableAttributedString(string: string)
    let paragraphStyle = NSMutableParagraphStyle()
    paragraphStyle.lineHeightMultiple = 1.25
    attributedString.addAttribute(NSParagraphStyleAttributeName, value: paragraphStyle, range: NSMakeRange(0, string.characters.count))
    attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.whiteColor(), range: NSMakeRange(0, string.characters.count))
    textView.attributedText = attributedString
    textView.backgroundColor = UIColor.clearColor()
    
    let pattern = "[a-zA-Z0-9]+"
    let regex = try! NSRegularExpression(pattern: pattern, options: [])
    let matches = regex.matchesInString(string, options: [], range: NSMakeRange(0, string.characters.count))
    
    func frameOfTextInRange(range:NSRange, inTextView textView:UITextView) -> CGRect {
        let beginning = textView.beginningOfDocument
        let start = textView.positionFromPosition(beginning, offset: range.location)!
        let end = textView.positionFromPosition(start, offset: range.length)!
        let textRange = textView.textRangeFromPosition(start, toPosition: end)!
        let rect = textView.firstRectForRange(textRange)
        return textView.convertRect(rect, fromView: textView)
    }
    
    for m in matches {
        let range = m.range
        var frame = frameOfTextInRange(range, inTextView: textView)
        frame = CGRectInset(frame, CGFloat(-1.2), CGFloat(2))
        frame = CGRectOffset(frame, CGFloat(0), CGFloat(2))
        let v = UIView(frame: frame)
        v.layer.cornerRadius = 2
        v.backgroundColor = UIColor(hue: 0.66, saturation: 0.6, brightness: 1, alpha: 1)
        textViewBG.addSubview(v)
    
    }
    textViewBG.addSubview(textView)
    


    to increase the space between the words we can alter the kerning of the whitespace

    import UIKit
    
    func frameOfTextInRange(range:NSRange, inTextView textView:UITextView) -> CGRect {
        let beginning = textView.beginningOfDocument
        let start = textView.positionFromPosition(beginning, offset: range.location)!
        let end = textView.positionFromPosition(start, offset: range.length)!
        let textRange = textView.textRangeFromPosition(start, toPosition: end)!
        let rect = textView.firstRectForRange(textRange)
        return textView.convertRect(rect, fromView: textView)
    }
    
    let string = "Lorem ipsum dolor sit amet"
    
    let textView = UITextView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
    textView.backgroundColor = UIColor.clearColor()
    
    textView.attributedText = {
        let attributedString = NSMutableAttributedString(string: string)
        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.lineHeightMultiple = 1.25
        attributedString.addAttribute(NSParagraphStyleAttributeName, value: paragraphStyle, range: NSMakeRange(0, string.characters.count))
        attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.whiteColor(), range: NSMakeRange(0, string.characters.count))
    
        let regex = try! NSRegularExpression(pattern: "\\s", options: [])
        let matches = regex.matchesInString(string, options: [], range: NSMakeRange(0, string.characters.count))
        for m in matches {
            attributedString.addAttribute(NSKernAttributeName, value: 6, range: m.range)
        }
        return NSAttributedString(attributedString: attributedString)
    }()
    
    let textViewBG = UIView(frame: textView.bounds)
    textViewBG.backgroundColor = UIColor.whiteColor()
    
    
    let pattern = "[^ ]+"
    let regex = try! NSRegularExpression(pattern: pattern, options: [])
    let matches = regex.matchesInString(string, options: [], range: NSMakeRange(0, string.characters.count))
    
    for m in matches {
        textViewBG.addSubview({
            let range = m.range
            var frame = frameOfTextInRange(range, inTextView: textView)
            frame = CGRectInset(frame, CGFloat(-3), CGFloat(2))
            frame = CGRectOffset(frame, CGFloat(0), CGFloat(3))
            let v = UIView(frame: frame)
            v.layer.cornerRadius = 2
            v.backgroundColor = UIColor(hue: 211.0/360.0, saturation: 0.35, brightness: 0.78    , alpha: 1)
            return v
        }())
    }
    
    textViewBG.addSubview(textView)
    

    0 讨论(0)
  • 2021-01-07 09:52

    You will have to create one label for each word....do it programmatically! I did it now, test please! hope u enjoy :-)

    import UIKit

    class ViewController: UIViewController {
    
    var arrayStrings = [String]()
    var x : CGFloat = 0
    var labelReference = 0
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
    
        let space = " "
        let string = "This is the line 1"
        var word = string.componentsSeparatedByString(space)
        print (word[0]) // prints "This"
        print(word[1]) // print "is"
    
        for var i = 0; i < word.count ; i++ {
    
    
            arrayStrings.append(word[i])
    
    
            let characteresCount = word[i].characters.count
    
    
            // change de "9" based on your font size
            let label = UILabel(frame: CGRectMake(CGFloat(32 + x), 30, CGFloat(characteresCount * 9), 25))
            x += label.frame.size.width + 2
            label.text = word[i]
            label.layer
            label.layer.borderWidth = 1.0
            label.layer.cornerRadius = 10
            view.addSubview(label)
    
    
          }
    
       }
    
    }
    
    0 讨论(0)
  • 2021-01-07 09:55

    SWIFT 5. Alternative solution

    The Solution Logic

    1. Converting Strings to Labels
    2. Customizing Labels
    3. Converting Labels to Images
    4. Converting Images to Attributed text
    5. Creating TextView
    6. Setting Attributed text to TextView

    You can find implementation here:

    https://github.com/vivatum/WordsAsTagLabels-Example

    0 讨论(0)
提交回复
热议问题