Skip to content

Instantly share code, notes, and snippets.

@shahankit
Created August 10, 2018 21:15
Show Gist options
  • Select an option

  • Save shahankit/d0091b80113fed30c1507ce8edc2542f to your computer and use it in GitHub Desktop.

Select an option

Save shahankit/d0091b80113fed30c1507ce8edc2542f to your computer and use it in GitHub Desktop.

Revisions

  1. shahankit revised this gist Aug 10, 2018. No changes.
  2. shahankit created this gist Aug 10, 2018.
    30 changes: 30 additions & 0 deletions ContentCell.swift
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,30 @@
    import UIKit

    class ContentCell: UITableViewCell {
    @IBOutlet weak var titleLabel: HighlightedTextLabel!

    override func awakeFromNib() {
    super.awakeFromNib()
    // Initialization code
    }

    // MARK: - Configure methods
    func configureCell(text: String) {
    let highlightColor = UIColor(red: 0, green: 1, blue: 0, alpha: 1)

    self.titleLabel.highlightColor = highlightColor
    let labelText = String(format: " %@ ", text)
    let totalCharacterCount = labelText.count;

    let attributedString = NSMutableAttributedString(string: labelText)
    let attributeFont = UIFont.systemFont(ofSize: 14)
    attributedString.addAttribute(NSFontAttributeName, value: attributeFont, range: NSMakeRange(0, totalCharacterCount))
    let paragraphStyle = NSMutableParagraphStyle()
    paragraphStyle.lineSpacing = 1.29
    attributedString.addAttribute(NSParagraphStyleAttributeName, value: paragraphStyle, range: NSMakeRange(0, totalCharacterCount))

    self.titleLabel.attributedText = attributedString

    self.selectionStyle = UITableViewCellSelectionStyle.none
    }
    }
    132 changes: 132 additions & 0 deletions HighlightedTextLabel.swift
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,132 @@
    import UIKit

    class HighlightedTextLabel: UILabel {
    var highlightColor: UIColor!

    override func draw(_ rect: CGRect) {
    let separatedLines = self.getSeparatedLines()
    let totalNumberOfLines = separatedLines.count
    if (totalNumberOfLines < 1) {
    super.draw(rect)
    return
    }

    let fontSize = self.font.pointSize
    let lineFillerSpaceWidth = CGFloat(9)
    let firstLineYOffset = CGFloat(1.0) // otherwise first line would look thinner because it would go outside of label bounds
    let interHighlightSeparation = CGFloat(3)
    let intraHighlightSeparation = CGFloat(fontSize + 3)

    let pi = CGFloat.pi

    let context = UIGraphicsGetCurrentContext()!

    // Draw parallel lines
    CGContext.setLineWidth(context)(1.5)
    CGContext.setStrokeColor(context)(highlightColor.cgColor)
    for (lineIndex, line) in separatedLines.enumerated() {
    let lineWidth = getLineWidth(line: line as! String)
    let lineStartX = lineIndex == 0 ? lineFillerSpaceWidth : 0
    let lineEndX = lineStartX + lineWidth
    let lineStartY = lineIndex == 0 ? firstLineYOffset : firstLineYOffset + ((intraHighlightSeparation + interHighlightSeparation) * CGFloat(lineIndex))
    let lineEndY = lineStartY + intraHighlightSeparation

    CGContext.beginPath(context)()
    CGContext.move(context)(to: CGPoint(x: lineStartX, y: lineStartY))
    CGContext.addLine(context)(to: CGPoint(x: lineEndX, y: lineStartY))
    CGContext.closePath(context)()
    CGContext.strokePath(context)()

    CGContext.beginPath(context)()
    CGContext.move(context)(to: CGPoint(x: lineStartX, y: lineEndY))
    CGContext.addLine(context)(to: CGPoint(x: lineEndX, y: lineEndY))
    CGContext.closePath(context)()
    CGContext.strokePath(context)()
    }

    // Draw circle at start of first line
    CGContext.beginPath(context)()
    let initialArcX = lineFillerSpaceWidth
    let initialArcRadius = intraHighlightSeparation / 2
    let initialArcY = firstLineYOffset + initialArcRadius
    let initialArcStartAngle = -pi/2
    let initialArcEndAngle = pi/2
    let initialCircleCenter = CGPoint(x: initialArcX, y: initialArcY)
    CGContext.addArc(context)(
    center: initialCircleCenter,
    radius: initialArcRadius,
    startAngle: initialArcStartAngle,
    endAngle: initialArcEndAngle,
    clockwise: true
    )
    CGContext.move(context)(to: CGPoint(x: 0, y: 0))
    CGContext.closePath(context)()
    CGContext.strokePath(context)()


    // Draw circle at end of last line
    let lastLineWidth = getLineWidth(line: separatedLines.last as! String)
    CGContext.beginPath(context)()
    let finalArcX = (totalNumberOfLines == 1 ? lineFillerSpaceWidth : 0) + lastLineWidth
    let finalArcRadius = intraHighlightSeparation / 2
    let finalArcY = firstLineYOffset + ((intraHighlightSeparation + interHighlightSeparation) * CGFloat(totalNumberOfLines - 1)) + initialArcRadius
    let finalArcStartAngle = pi/2
    let finalArcEndAngle = -pi/2
    let finalCircleCenter = CGPoint(x: finalArcX, y: finalArcY)
    CGContext.addArc(context)(
    center: finalCircleCenter,
    radius: finalArcRadius,
    startAngle: finalArcStartAngle,
    endAngle: finalArcEndAngle,
    clockwise: true
    )
    CGContext.move(context)(to: CGPoint(x: 0, y: 0))
    CGContext.closePath(context)()
    CGContext.strokePath(context)()

    super.draw(rect)
    }

    func getSeparatedLines() -> [Any] {
    if self.lineBreakMode != NSLineBreakMode.byWordWrapping {
    self.lineBreakMode = .byWordWrapping
    }
    var lines = [Any]() /* capacity: 10 */
    let wordSeparators = CharacterSet.whitespacesAndNewlines
    var currentLine: String? = self.text
    let textLength: Int = (self.text?.count ?? 0)
    var rCurrentLine = NSRange(location: 0, length: textLength)
    var rWhitespace = NSRange(location: 0, length: 0)
    var rRemainingText = NSRange(location: 0, length: textLength)
    var done: Bool = false
    while !done {
    // determine the next whitespace word separator position
    rWhitespace.location = rWhitespace.location + rWhitespace.length
    rWhitespace.length = textLength - rWhitespace.location
    rWhitespace = (self.text! as NSString).rangeOfCharacter(from: wordSeparators, options: .caseInsensitive, range: rWhitespace)
    if rWhitespace.location == NSNotFound {
    rWhitespace.location = textLength
    done = true
    }
    let rTest = NSRange(location: rRemainingText.location, length: rWhitespace.location - rRemainingText.location)
    let textTest: String = (self.text! as NSString).substring(with: rTest)
    let fontAttributes: [String: Any]? = [NSFontAttributeName: font]
    let maxWidth = (textTest as NSString).size(attributes: fontAttributes).width
    if maxWidth > self.bounds.size.width {
    lines.append(currentLine?.trimmingCharacters(in: wordSeparators) ?? "")
    rRemainingText.location = rCurrentLine.location + rCurrentLine.length
    rRemainingText.length = textLength - rRemainingText.location
    continue
    }
    rCurrentLine = rTest
    currentLine = textTest
    }
    lines.append(currentLine?.trimmingCharacters(in: wordSeparators) ?? "")
    return lines
    }

    func getLineWidth(line: String) -> CGFloat {
    let fontAttributes: [String: Any]? = [NSFontAttributeName: self.font]
    return (line as NSString).size(attributes: fontAttributes).width
    }
    }