Clipped text on UILabel - swift

I'm using custom a font for UILabel but there is a strange problem, for some characters the text is being clipped:
The label should be like this (label frame has enlarged manually):
This is the code to add the label to the gray view:
let string = "کیخسروی"
let font = UIFont(name: "IranNastaliq", size: 30)!
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineBreakMode = .byWordWrapping
paragraphStyle.alignment = .center
let attributes: [NSAttributedStringKey: Any] = [
.font: font,
.paragraphStyle: paragraphStyle
]
let mutabbleAttributedString = NSMutableAttributedString(string: string, attributes: attributes)
let rectSize = mutabbleAttributedString.size()
let label = UILabel(frame: CGRect(x: 0, y: 0, width: rectSize.width, height: rectSize.height))
label.font = font
label.attributedText = mutabbleAttributedString
label.backgroundColor = UIColor.yellow
label.textAlignment = .center
let size = CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)
let width = label.sizeThatFits(size).width
let height = label.sizeThatFits(size).height
let frame = CGRect(x: 0, y: 0, width: width, height: height)
label.frame = frame
self.myView.addSubview(label)
label.center = self.myView.center
Seems sizeThatFits() does not calculate the bounds correctly.
I have to mention this clipping only happens while using some custom fonts.

Related

How to calculate boundRect correctly for NSAttributedString When apply shadow

I tried apply shadow effect to UILabel using NSAttributeString. I want to change the size of UILabel whenever change shadow offset. However, it doesn't calculate correct frame and ignore shadow offset. How can I achieve?
let textView = UILabel(frame: CGRect(x: 20, y: 100, width: 300, height: 50))
textView.layer.borderColor = UIColor.red.cgColor
textView.layer.borderWidth = 1
textView.numberOfLines = 0
textView.text = "hyHgjpQ\nhyHgjpQ\nhyHgjpQ"
textView.font = UIFont(name: "DamascusSemiBold", size: 40)
textView.textColor = .white
textView.textAlignment = .center
self.view.addSubview(textView)
var textAttributes: [NSAttributedString.Key: AnyObject] = [:]
// font name & size
let font = UIFont(name: "HelveticaNeue", size: 50)
textAttributes[NSAttributedString.Key.font] = font
// shadow
let shadow = NSShadow()
shadow.shadowBlurRadius = 10
shadow.shadowOffset = CGSize(width: 10, height: 30)
shadow.shadowColor = UIColor.red
textAttributes[NSAttributedString.Key.shadow] = shadow
textView.attributedText = NSAttributedString(string: textView.text ?? "", attributes: textAttributes)
let bound = textView.text!.boundingRect(with: CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude),
options: .usesLineFragmentOrigin,
attributes: textAttributes,
context: nil)
textView.bounds = bound
Result

Add label in center of imageView

I have the two images like in the picture at the end of the question (the image of a list and a red dot). I want to add a label in the center of the red dot. This is my code that doesn't work:
image = UIImageView(image: UIImage(named: "pallino"))
image.frame = CGRect(x: 55, y: self.view.frame.height-60, width: 22, height: 22)
self.view.addSubview(image)
image.layer.cornerRadius = image.frame.width/2
label = UILabel(frame: CGRect(x: self.image.center.x, y: self.image.center.y, width: image.frame.size.width, height: image.frame.size.height))
label.text = "4"
label.font = UIFont(name:"HelveticaNeue-Bold", size: 15.0)
label.translatesAutoresizingMaskIntoConstraints = false
label.textColor = UIColor.black
image.addSubview(label)
Can someone tell me were am I wrong?
Problem in this line:
label = UILabel(frame: CGRect(x: self.image.center.x, y: self.image.center.y, width: image.frame.size.width, height: image.frame.size.height))
self.image.center.x - The center point is specified in points in the coordinate system of its superview, it is mean that self.image.center is not center of image
You need frame for label, something like this:
let imageSize = 22
let frame = CGRect(x: 0, y: 0, width: imageSize, height: imageSize)
let label = UILabel(frame: frame)
label.aligment = .center
You can set constraint in your label(centered Horizontally and Vertically). Try with the following code.
let label = UILabel()
label.text = "4"
label.font = UIFont(name:"HelveticaNeue-Bold", size: 15.0)
label.translatesAutoresizingMaskIntoConstraints = false
label.textColor = UIColor.black
image.addSubview(label)
label.centerXAnchor.constraint(equalTo: self.image.centerXAnchor).isActive = true
label.centerYAnchor.constraint(equalTo: self.image.centerYAnchor).isActive = true
To center the label in UIImageView you can refer to this example which is tested and working solution.
extension UIImageView {
/// Create label programmatically
/// - Returns: UILabel
private func ageSensitiveLabel() -> UILabel {
let label = UILabel(frame: CGRect(x: 0, y: 0, width: self.bounds.width, height: self.bounds.height))
label.text = "Content"
label.font = .systemFont(ofSize: 5.0)
label.textAlignment = .center
label.numberOfLines = 0
label.minimumScaleFactor = 0.5
label.adjustsFontSizeToFitWidth = true
label.baselineAdjustment = .alignCenters
label.textColor = .white
return label
}
/// Add label as subview to UIImageView
func addAgeSensitiveLabel() {
self.subviews.forEach { view in
DispatchQueue.main.async {
view.removeFromSuperview()
}
}
self.addSubview(ageSensitiveLabel())
}
}
Use it with UIImageView
imageView.addAgeSensitiveLabel()

manually setting titleView of navigationItem is not alligned vertically

I am using this func inside a UIViewController extension to add a title that adjusts font to fit width.
extesion UIViewController {
func setTitleDifferentSizes(title: String){
self.title = title
guard let navigationBarHeight: CGFloat =
self.navigationController?.navigationBar.frame.height else{
return
}
let tlabel = UILabel(frame: CGRect(x: 0.0, y: 0.0, width:
200.0, height: navigationBarHeight))
tlabel.text = self.title
tlabel.textColor = UIColor.white
tlabel.font = font24
tlabel.backgroundColor = UIColor.clear
tlabel.adjustsFontSizeToFitWidth = true
self.navigationItem.titleView = tlabel
}
}
I took this solution from this SO question and changed it a little bit:
How to resize Title in a navigation bar dynamically
Now the issue I have is that the text of the title is not aligned vertically to the other navigation bar items, as you can see in the images, I show one where I just setup the title without using the above method, and the text there cannot fit but it is aligned properly, and the other image is using the method above where the text fits but it is not aligned.
try this:-
func setTitleDifferentSizes(title: String){
self.title = title
guard let navigationBarHeight: CGFloat =
self.navigationController?.navigationBar.frame.height else{
return
}
let attributedString = NSMutableAttributedString(string: title)
let myAttribute = [ NSForegroundColorAttributeName: UIColor.white ,NSFontAttributeName: font24]
attributedString.addAttributes(myAttribute, range: NSRange(location: 0, length: attributedString.string.characters.count))
attributedString.addAttributes([NSBaselineOffsetAttributeName:6.0], range: NSRange(location: 0, length: title.characters.count)
)
let tlabel = UILabel(frame: CGRect(x: 0.0, y: 0.0, width:
200.0, height: navigationBarHeight))
tlabel.attributedText = attributedString
tlabel.backgroundColor = UIColor.clear
tlabel.adjustsFontSizeToFitWidth = true
tlabel.minimumScaleFactor = 0.2
tlabel.textAlignment = .center
self.navigationItem.titleView = tlabel
}
if you want to adjust the position of text please change the float value of NSBaselineOffsetAttributeName to set the vertical alignment.

How to set button width based on text for dynamically created button in swift 3?

I created the dynamic buttons. I need to change the width of button based on tittle label text. Here is my code.
for i in 0..<holdingSize {
let button = UIButton(type: .custom)
if i == 0 {
frame = CGRect(x: 10, y: 5, width: 100, height: 30)
}else{
buttonY = buttonY + 110
frame = CGRect(x: buttonY, y: 5, width: 100, height: 30)
}
button.setTitle("\(arrayOfHoldings[i])", for: UIControlState.normal) // We are going to use the item name as the Button Title here.
button.titleLabel?.text = "\(arrayOfHoldings[i])"
button.titleLabel?.font = UIFont(name: (button.titleLabel?.font.fontName)!, size: 15)
button.setTitleColor(Colors.green, for: .normal)
button.sizeToFit()
}
Try this
func labelSizeWithString(text: String,fontSize: CGFloat, maxWidth : CGFloat,numberOfLines: Int) -> CGRect{
let font = UIFont.systemFontOfSize(fontSize)//(name: "HelveticaNeue", size: fontSize)!
let label = UILabel(frame: CGRectMake(0, 0, maxWidth, CGFloat.max))
label.numberOfLines = numberOfLines
label.font = font
label.text = text
label.sizeToFit()
return label.frame
}
This will give you the frame of the label, you can set the height of your button from that.
FOR SWIFT 3.0
func labelSize(for text: String,fontSize: CGFloat, maxWidth : CGFloat,numberOfLines: Int) -> CGRect{
let font = UIFont.systemFont(ofSize: fontSize)//(name: "HelveticaNeue", size: fontSize)!
let label = UILabel(frame: CGRect(x: 0, y: 0, width: maxWidth, height: CGFloat.leastNonzeroMagnitude))
label.numberOfLines = numberOfLines
label.font = font
label.text = text
label.sizeToFit()
return label.frame
}

Can i have 2 colours in my navigation bar Tittle?

I want to set 2 colours in my navigation bar title.
If i cant to do that, how can i center perfectly an image as tittle of my navigation bar?
I tried:
let logo = UIImage(named: "LogoMV_BAR#2x");
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 100, height: 30))
imageView.image = logo
imageView.contentMode = UIViewContentMode.ScaleAspectFit
self.navigationItem.titleView = imageView
And it looks so small and not centered.
Thanks guys!
Thanks user Larme, your answer helped me a lot. Thats how i do it:
let A = NSMutableAttributedString(string: "Label Test", attributes: [NSFontAttributeName: UIFont(name: "Georgia", size: 18)!])
A.addAttribute(NSForegroundColorAttributeName, value: UIColor.blueColor(), range: NSRange(location: 6, length: 5))
let LabelTexto: UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 30))
LabelText.attributedText = A
self.navigationItem.titleView = LabelText