Making NSMutableAttributedString and sizeThatFits work together - ios

I'm having issues making NSMutableAttributedString and sizeThatFits work together. I have a UILabel that must be no wider than a constant self.frame.size.width-usernameX-horizontalMargin. I want the UILabel to be one line if it fits or two lines with a hyphen if it is too long. Currently I am using this code:
let usernameX = profilePhoto.frame.size.width+horizontalMargin
let username = UILabel()
username.adjustsFontSizeToFitWidth = false
username.font = UIFont(name: "SFUIDisplay-Regular", size: 18)
username.numberOfLines = 0
username.translatesAutoresizingMaskIntoConstraints = false
//Set hyphenation
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.hyphenationFactor = 0.2
username.attributedText = NSMutableAttributedString(string: displayName, attributes: [NSParagraphStyleAttributeName: paragraphStyle])
let maxSize = CGSize(width: self.frame.size.width-usernameX-horizontalMargin, height: CGFloat.max)
let requiredSize = username.sizeThatFits(maxSize)
username.frame = CGRect(x: usernameX, y: (self.frame.size.height/2)-21, width: requiredSize.width, height: requiredSize.height)
self.addSubview(username)
Currently the text displays as just one line with a hyphen. The second line isn't showing. Any ideas what I might be doing wrong here? I have tried setting the number of lines to 2, that made no difference. Any pointers would be really appreciated.
Thanks!

You need to include your font also in attributes, else it will take default fond for attributed text. Can you try this out?
let attributedString = NSMutableAttributedString(string: displayName, attributes: [NSParagraphStyleAttributeName: paragraphStyle, NSFontAttributeName : UIFont(name: "SFUIDisplay-Regular", size: 18)])
var newFrame = attributedString.boundingRectWithSize(CGSizeMake(self.frame.size.width-usernameX-horizontalMargin, CGFloat.max), options: NSStringDrawingOptions.UsesLineFragmentOrigin , context: nil)
username.frame = CGRect(x: usernameX, y: (self.frame.size.height/2)-21, width: newFrame.size.width, height: newFrame.size.height)
If you want to use sizeThatFits you can use following
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.hyphenationFactor = 0.2
username.attributedText = NSMutableAttributedString(string: displayName, attributes: [NSParagraphStyleAttributeName: paragraphStyle, NSFontAttributeName : UIFont(name: "SFUIDisplay-Regular", size: 18)])
let maxSize = CGSize(width: self.frame.size.width-usernameX-horizontalMargin, height: CGFloat.max)
let requiredSize = username.sizeThatFits(maxSize)
username.frame = CGRect(x: usernameX, y: (self.frame.size.height/2)-21, width: requiredSize.width, height: requiredSize.height)
self.addSubview(username)

Related

How change height in navigation title?

I need to set the rockwell-bold font in the navigation title, but it is cropped for me. how can I fix this problem or change the height of the navigation titleenter image description here
let customText = NSLocalizedString("your_title", comment: "")
let title:NSMutableAttributedString = NSMutableAttributedString(string: customText, attributes: [.font: UIFont(name: "font_name", size: 20.0) ])
let size = title.size()
let width = size.width
guard let height = navigationController?.navigationBar.frame.size.height else {return}
let titleLabel = UILabel(frame: CGRect(x: 0,y: 0, width: width, height: height))
titleLabel.attributedText = title
titleLabel.numberOfLines = 0
titleLabel.textAlignment = .center
navigationItem.titleView = titleLabel

Getting wrong text height?

I am using below code to determine the hight of text , it works fine for small text but if text is large it gives me wrong height(too much space at bottom of textview) how to fix that.
let textView = UITextView (frame: CGRectMake(0,0,maxWidth, 10))
textView.font = font
textView.text = text
//textView.textContainerInset = UIEdgeInsetsZero
let fixedWidth = textView.frame.size.width
let newSize = textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.max))
var newFrame = textView.frame
newFrame.size = CGSize(width: max(newSize.width, fixedWidth), height: newSize.height)
textView.frame = newFrame;
return textView.frame.height
This will be your text height in textview.
let textView = UITextView (frame: CGRectMake(0,0,maxWidth, 10))
textView.font = font
textView.text = text
let height = textView.conentSize.height
Use an extension on String
extension String {
func height(withConstrainedWidth width: CGFloat, font: UIFont) -> CGFloat {
let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
let boundingBox = boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)
return boundingBox.height
}
}
and also on NSAttributedString (which is very useful at times)
extension NSAttributedString {
func height(withConstrainedWidth width: CGFloat) -> CGFloat {
let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
let boundingBox = boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, context: nil)
return boundingBox.height
}
func width(withConstrainedHeight height: CGFloat) -> CGFloat {
let constraintRect = CGSize(width: .greatestFiniteMagnitude, height: height)
let boundingBox = boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, context: nil)
return boundingBox.width
}
}
Try with this method
static func neededHeigthForText(text:String,font:UIFont,maxWidth:CGFloat) ->CGFloat
{
let options : NSStringDrawingOptions = [.usesLineFragmentOrigin,.usesFontLeading]
let style : NSMutableParagraphStyle = NSMutableParagraphStyle()
style.lineBreakMode = .byWordWrapping
let textAttributes = [NSFontAttributeName:font]
let size = NSString(string: text).boundingRect(with: CGSize(width: maxWidth, height: CGFloat.greatestFiniteMagnitude) , options: options, attributes: textAttributes, context: nil).size
return size.height
}
I hope this helps you

CATextLayer not visible

I have implemented a function to draw the text use of CATextLayer. But after drawing the text is not visible.
Here is my code:
func addText() -> CATextLayer{
let rect:CGRect = CGRect(x: 50, y: 600, width: 120, height: 60)
let myAttributes = [
NSFontAttributeName: UIFont(name: "HelveticaNeue-Thin", size:18)!,
NSForegroundColorAttributeName: UIColor.black.cgColor
] as [String : Any]
let myAttributedString = NSAttributedString(string: "TEST STRING", attributes: myAttributes)
let textLayer = CATextLayer()
textLayer.bounds = rect
textLayer.string = myAttributedString
textLayer.position = CGPoint(x:150,y:400)
textLayer.alignmentMode = kCAAlignmentCenter
textLayer.displayIfNeeded()
return textLayer
}
Does anyone know the problem?

How to dynamically draw image for button in iOS?

This is the result I need to accomplish:
I need the icons with basic image: basket and additionally I need to put there UILabel with some text: once it is just a number, and once it is an amount to pay. Any ideas?
This is my example:
var image = UIImage(named: "cart")!
let text = "1 PLN"
UIGraphicsBeginImageContext(CGSizeMake(80, 50))
let context = UIGraphicsGetCurrentContext()
let label = UILabel(frame: CGRectZero)
label.text = text
label.font = UIFont.systemFontOfSize(10)
label.sizeToFit()
let width = max(label.frame.size.width + 10, 15)
let height = CGFloat(15)
CGContextSetFillColorWithColor(context, UIColor.greenColor().CGColor)
CGContextFillRect(context, CGRectMake(0, 0, image.size.width, image.size.height))
image.drawInRect(CGRectMake(80/2-50/2, 0, 50, 50))
let path = UIBezierPath(roundedRect: CGRectMake(75-width, 45-height, width, height), cornerRadius: 5)
path.lineWidth = 2
UIColor.redColor().setStroke()
UIColor.yellowColor().setFill()
path.stroke()
path.fill()
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = NSTextAlignment.Center
let attributes = [NSFontAttributeName: UIFont.systemFontOfSize(10.0), NSParagraphStyleAttributeName: paragraphStyle]
(text as NSString).drawInRect(CGRectMake(75-width, 45-height, width, height), withAttributes: attributes)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
The result is following:
Some examples for different text:

How to make a strechable image according to label height in swift

I have objective-c code but i want swift code. please suggest me a swift code. i have tried all the ways but unable to find the proper answer.
Hey mate please find below code if it helps you
var lbl = UILabel(frame: CGRectMake(8,8, 240, CGFloat.max))
lbl.numberOfLines = 0
lbl.lineBreakMode = NSLineBreakMode.ByWordWrapping
lbl.font = UIFont(name: "Helvetica", size: 16.0)
lbl.text = "Sample text"
lbl.sizeToFit()
let imageContainerMessage = UIImage(named: "balloon_unread_left.png")!.stretchableImageWithLeftCapWidth(15, topCapHeight: 17 )
let sizeMessageLabelMax = CGSizeMake(240, 9999)
let expectedSizeMessage = lbl.sizeThatFits(sizeMessageLabelMax)
lbl.frame = CGRect(origin: CGPoint(x: 15, y: 10), size: expectedSizeMessage)
var imageContainer = UIImageView(frame: CGRect(origin: CGPoint(x: 0, y: 0), size: CGSizeMake(expectedSizeMessage.width + 25, expectedSizeMessage.height + 25)))
imageContainer.image = imageContainerMessage
imageContainer.addSubview(lbl)

Resources