Skip to content

Instantly share code, notes, and snippets.

@simme
Last active April 25, 2021 21:57
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save simme/a9fcc60d94c0cb17750f96c692316f10 to your computer and use it in GitHub Desktop.
Save simme/a9fcc60d94c0cb17750f96c692316f10 to your computer and use it in GitHub Desktop.
Fades the last line of a `UITextView` horizontally, instead of truncating it.
extension UITextView {
var lineFrames: [CGRect] {
let numberOfGlyphs = layoutManager.numberOfGlyphs
var numberOfLines = 0
var index = 0
var lineRange = NSRange()
let maxNumberOfLines = textContainer.maximumNumberOfLines
var lineRects = [CGRect]()
while (index < numberOfGlyphs) {
let frame = layoutManager.lineFragmentRect(forGlyphAt: index, effectiveRange: &lineRange)
lineRects.append(frame)
index = NSMaxRange(lineRange);
numberOfLines = numberOfLines + 1
if maxNumberOfLines != 0 && numberOfLines == maxNumberOfLines {
break
}
}
return lineRects
}
func fadeLastVisibleLine() {
let mask = CALayer()
mask.frame = layer.bounds
let topInset = self.textContainerInset.top
zip(0..<lineFrames.count, lineFrames).forEach { args in
let (index, frame) = args
if index == lineFrames.count - 1 {
let gradientMask = CAGradientLayer()
gradientMask.colors = [UIColor.white.cgColor, UIColor.clear.cgColor]
gradientMask.startPoint = CGPoint(x: 0.7, y: 0)
gradientMask.endPoint = CGPoint(x: 0.95, y: 0)
gradientMask.frame = frame.offsetBy(dx: 0, dy: topInset)
mask.addSublayer(gradientMask)
} else {
let solidMask = CALayer()
solidMask.backgroundColor = UIColor.white.cgColor
solidMask.opacity = 1
solidMask.frame = frame.offsetBy(dx: 0, dy: topInset)
mask.addSublayer(solidMask)
}
}
self.layer.mask = mask
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment