Reputation: 730
I'm trying to put the temperature in my app. I would like to show it like that:
But all I'm able to get is that:
I have tried to use this code to align the two label on top:
@IBDesignable class TopAlignedLabel: UILabel {
override func drawText(in rect: CGRect) {
if let stringText = text {
let stringTextAsNSString = stringText as NSString
let labelStringSize = stringTextAsNSString.boundingRect(with: CGSize(width: self.frame.width,height: CGFloat.greatestFiniteMagnitude), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil).size
super.drawText(in: CGRect(x:0,y: 0,width: self.frame.width, height:ceil(labelStringSize.height)))
} else {
super.drawText(in: rect)
}
}
}
It worked on for the '°C' but it's not working for the 25. Can someone help me find a solution to my problem ?
Upvotes: 1
Views: 144
Reputation: 25535
A very simple way to solve this is with attributed strings:
let tempText = "25˚C"
let baseFont = UIFont.systemFont(ofSize: 23.0)!
let superscriptFont = UIFont.systemFont(ofSize: 15.0)!
let attrStr = NSMutableAttributedString(string: tempText, attributes: [NSFontAttributeName: baseFont])
attrStr.addAttributes([NSFontAttributeName: superscriptFont, NSBaselineOffsetAttributeName: 10.0], range: NSMakeRange(2,2))
myLabel.attributedText = attrStr
You can keep adding more different attributes on any range you want by using the addAttributes
method.
Upvotes: 1
Reputation: 77638
A font has multiple characteristics, including Ascender, Descender, CapHeight, etc... So what your code gets is not a way to align the character glyphs flush with the top of the label frame, but rather it aligns the Font bounding box to the top of the frame.
Calculating the offset between font metrics might give you what you're after. Here is one example (you can run it in a Playground page):
import UIKit
import PlaygroundSupport
class TestViewController : UIViewController {
let labelOne: UILabel = {
let label = UILabel()
label.font = UIFont.systemFont(ofSize: 60.0)
label.text = "25"
label.backgroundColor = .cyan
label.translatesAutoresizingMaskIntoConstraints = false
label.numberOfLines = 1
label.textAlignment = .right
return label
}()
let labelTwo: UILabel = {
let label = UILabel()
label.font = UIFont.systemFont(ofSize: 24.0)
label.text = "°C"
label.backgroundColor = .cyan
label.translatesAutoresizingMaskIntoConstraints = false
label.numberOfLines = 1
return label
}()
override func viewDidLoad() {
super.viewDidLoad()
// add the scroll view to self.view
self.view.addSubview(labelOne)
self.view.addSubview(labelTwo)
// constrain the scroll view to 8-pts on each side
labelOne.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 8.0).isActive = true
labelOne.topAnchor.constraint(equalTo: view.topAnchor, constant: 8.0).isActive = true
labelTwo.leftAnchor.constraint(equalTo: labelOne.rightAnchor, constant: 2.0).isActive = true
if let f1 = labelOne.font, let f2 = labelTwo.font {
let offset = (f1.ascender - f1.capHeight) - (f2.ascender - f2.capHeight)
labelTwo.topAnchor.constraint(equalTo: labelOne.topAnchor, constant: offset).isActive = true
}
}
}
let vc = TestViewController()
vc.view.backgroundColor = .yellow
PlaygroundPage.current.liveView = vc
And this is the result:
Depending on what font you are actually using, though, that may not be good enough. If so, you'll want to look into CoreText / CTFont
/ CTFontGetGlyphsForCharacters()
/ etc.
Upvotes: 1