// // Copyright © 2016 Nattawut Singhchai <jadedragon17650@gmail.com> // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // import UIKit @IBDesignable public class InspectableLabel: UILabel { public var truncateLastVisibleLine:Bool = true @IBInspectable public var charSpacing: CGFloat = 0.0 { didSet { updateView() } } @IBInspectable public var lineSpacing: CGFloat = 0.0{ didSet { updateView() } } @IBInspectable public var paragraphSpacing: CGFloat = 0.0 { didSet { updateView() } } public override func prepareForInterfaceBuilder() { updateView() } public override func drawRect(rect: CGRect) { updateView() } var paragraph = NSMutableParagraphStyle() { didSet { textAlignment = paragraph.alignment lineSpacing = paragraph.minimumLineHeight paragraphSpacing = paragraph.paragraphSpacingBefore } } public func updateView() { paragraph.alignment = textAlignment paragraph.minimumLineHeight = lineSpacing paragraph.maximumLineHeight = lineSpacing paragraph.paragraphSpacingBefore = paragraphSpacing paragraph.lineBreakMode = lineBreakMode var attr = [NSFontAttributeName:font, NSParagraphStyleAttributeName: paragraph, NSForegroundColorAttributeName: textColor ] attr[NSKernAttributeName] = charSpacing if let text = text { attributedText = NSAttributedString(string: text, attributes:attr) } var options:NSStringDrawingOptions = [.UsesLineFragmentOrigin,.UsesFontLeading] if truncateLastVisibleLine { options.insert(.TruncatesLastVisibleLine) } attributedText?.drawWithRect(CGRect(origin: CGPoint(x: 0, y: yDrawingSpace), size: CGSize(width: frame.width, height: ceil(frame.height - yDrawingSpace))), options: options, context: nil) } var yDrawingSpace: CGFloat { let ls = -lineSpacing + font.pointSize + (font.capHeight - font.xHeight) return lineSpacing <= 0 ? 0 : ls } public override func sizeThatFits(size: CGSize) -> CGSize { guard let attributedText = attributedText else { return CGSizeZero } return InspectableLabel.sizeThatFitsWithAttributedText(attributedText, size: size, font: font, paragraph: paragraph) } private class func sizeThatFitsWithAttributedText(attributedText: NSAttributedString,size:CGSize,font:UIFont,paragraph:NSParagraphStyle) -> CGSize { let calcSize = attributedText.boundingRectWithSize(size, options: [.UsesLineFragmentOrigin,.UsesFontLeading], context: nil) var height = calcSize.height if paragraph.minimumLineHeight > 0 { height = calcSize.height - paragraph.minimumLineHeight + font.pointSize - font.descender } return CGSize( width: ceil(calcSize.width), height: ceil(height) ) } } extension NSAttributedString { public func in_boundingSizeWithSize(size: CGSize) -> CGSize { let pointer = NSRangePointer() guard let paragraph = attribute(NSParagraphStyleAttributeName, atIndex: 0, effectiveRange: pointer) as? NSParagraphStyle, font = attribute(NSFontAttributeName, atIndex: 0, effectiveRange: pointer) as? UIFont else { return CGSizeZero } return InspectableLabel.sizeThatFitsWithAttributedText(self, size: size, font: font, paragraph: paragraph) } } extension String { public func in_boundingSizeWithSize(size: CGSize, font: UIFont, lineSpacing: CGFloat? = nil, charSpacing:CGFloat? = nil, paragraphSpacing:CGFloat? = nil) -> CGSize { let paragraph = NSMutableParagraphStyle() if let lineSpacing = lineSpacing { paragraph.minimumLineHeight = lineSpacing } if let paragraphSpacing = paragraphSpacing { paragraph.paragraphSpacingBefore = paragraphSpacing } var attr:[String:AnyObject] = [ NSFontAttributeName:font ] if let charSpacing = charSpacing { attr[NSKernAttributeName] = charSpacing } return InspectableLabel.sizeThatFitsWithAttributedText(NSAttributedString(string: self, attributes: attr), size: size, font: font, paragraph: paragraph) } }