In my project, i am using scaling for UI components. I am able to scale the text for UIlabel like below and it's working in all device:
1. Autoshrinks - minimum font scale set it to 0.5
2. No of lines - 0
3. Enable dynamic type in attribute inspector
4. adjustFontSizeToWidth to true
But when i am trying to adjust font for UI Button using beolow steps and i am not able to scale the text for UI button.
button.titleLabel?.numberOfLines = 1 // Tried with 0 also
button.titleLabel?.adjustsFontSizeToFitWidth = true
button.titleLabel?.lineBreakMode = // tried differenet linebreakmode
Could anyone have an idea of scaling UI Button text?
Are you sure it's not working?
Edit - After comments...
UIKit elements such as UILabel / UIButton / etc to not have a built-in "auto-adjust font height" property.
I don't work for Apple, so just guessing that is (at least in part) due to the fact that, in general...
Based on screen height, the UI is designed to either:
provide more or less information, e.g. more rows in a table, or
adjust vertical spacing between elements
That doesn't mean you can't or shouldn't adjust your font sizes... it just means you have to do it manually.
Couple options:
set the font-size at run-time, as suggested by Duncan
use a UIAppearance proxy to set the font-size, again at run-time
in either case, you could use a height-to-fontSize table or a "percentage" calculation.
Another option would be a custom class that sets the font-size based on the constrained button height.
Here's a simple example (note: for demonstration purposes only):
class AutoFontSizeButton: UIButton {
override func layoutSubviews() {
super.layoutSubviews()
guard let fnt = titleLabel?.font else { return }
// default system type button has 6-pts top / bottom inset
// and font size is 15/18ths of that height
let h = ((bounds.height - 12.0) * (15.0 / 18.0)).rounded()
let fs = fnt.pointSize
if h != fs {
titleLabel?.font = UIFont(descriptor: fnt.fontDescriptor, size: h)
}
}
}
Result - the top three (yellow) buttons are 30, 40 and 50-points in height, with the default font-size of 15. The bottom three (green) buttons are again 30, 40 and 50-points in height, but the font-size is automatically set at run-time:
I don't think there is a way to get the font to auto-size. However, if you set the button's titleLabel.font to a specific font size the button will update to use the new font size, including resizing the button.
Use code like this:
let size: CGFloat = useLargeFont ? 50.0 : 17.0 //Change as needed
if let buttonFont = button.titleLabel?.font {
button.titleLabel?.font = buttonFont.withSize(size)
}
I have some UILabel with the default system font. But when I install my app on iPad or iPhone with iOS 13.1 the fonts change to something like Times New Roman! Why does this happen? I am sure the label's text is Plain and the font is System. How can I fix this issue?
PS: I have downloaded all SF fonts from Apple web site, and still no luck!
I found the solution, the problem comes with detecting the current label's font. I changed:
descriptions.font = UIFont(name: (descriptions.font?.fontName)!, size: 22)
to
descriptions.font = UIFont.systemFont(ofSize: 22)
and problem solved.
Use UIFontDescriptor
I was having the same issue on iOS 13. Fixed it by using fontDescriptor instead of fontName. I have UILabel in my storyboard connected to its view controller via IBOutlet with font as Text Styles - Callout.
#IBOutlet weak var lblText: UILabel!
Below one didn't worked as expected and showing Times New Roman font:
let font = UIFont.init(name: lblText.font.fontName, size: 50.0)!
lblText.font = font
lblText.text = "Times Coding :)"
Solution using UIFontDescriptor:
let font = UIFont.init(descriptor: lblText.font.fontDescriptor, size: 50.0)
lblText.font = font
lblText.text = "Times Coding :)"
This way it will pick the font you set to a label in your storyboard, you don't need to hardcode the font name.
It seems like Apple is pushing to use the initializer with the weightage. Passing it with the name seems to break it ".SFUI-Regular".
The workaround for this is to use the function with weight like this : UIFont(systemFont:UIFont.systemFontSize, weight: .regular).
I have an edit and a delete tableViewRowAction in my tableViewCell. Currently I'm using the built in emojis to use as my title, but it is too small. How do I make the font larger?
I know we can only customise a limited amount of things in the tableViewRowAction. But is there a way to go around it to make just the title font bigger?
I checked other threads and most of them used:
UIButton.appearance().setAttributedTitle(NSAttributedString(string: "Your Button", attributes: attributes), forState: .Normal)
with a set attribute that determines the font size of course. However, this affects ALL buttons, and that isn't good.
Any help is much appreciated! Thanks!
you are setting this to UIButton so it is set for all UIButton objects.
You can set it for specific button object like,
let myButton: UIButton = UIButton() //your button here
let attributedStr: NSAttributedString = NSAttributedString()
myButton.setAttributedTitle(attributedStr, forState: .Normal)
Update :
You can set title as attributed string.
check Apple documentation for that and refer this answer for more details
Hope this will help :)
I'm trying to create a messaging application and am encountering a very strange issue.
The reason there is so much space between "Thomas" and the bottom of the text bubble is becasue the UILabel is creating another line. Currently I'm setting the label's text using the attributedText property, and passing in a NSMutableParagraphStyle with a line spacing of 8. If I set the line spacing to 0, the space between "Thomas" and the bottom of the text bubble goes away like so:
Here's where it gets strange though. If I set the paragraph line spacing back to 8, and add a couple more characters to the line, the text bubble appears without the extra line:
All help is greatly appreciated :)
Here is my code:
class MessageTableViewCell: UITableViewCell {
var didSetupConstraints = false
var thumbnail = UIImageView.newAutoLayoutView()
let messageTailIcon = UIImageView.newAutoLayoutView()
var messageView = UIView.newAutoLayoutView()
var messageLabel = UILabel.newAutoLayoutView()
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setupViews()
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setupViews() {
thumbnail.image = UIImage(named: "ThomasBaldwin")
thumbnail.layer.cornerRadius = 17.5
thumbnail.clipsToBounds = true
messageTailIcon.image = UIImage(named: "MessageTailIcon")
messageView.backgroundColor = Application.greyColor
messageView.layer.cornerRadius = 10
let paragraphStyle = NSMutableParagraphStyle.new()
paragraphStyle.lineSpacing = 8
messageLabel.numberOfLines = 0
messageLabel.layer.cornerRadius = 10
messageLabel.attributedText = NSMutableAttributedString(
string: "Thomas says hello",
attributes: [
NSFontAttributeName: UIFont(name: "AvenirNextLTPro-Regular", size: 12.5)!,
NSForegroundColorAttributeName: UIColor.colorFromCode(0x262626),
NSBackgroundColorAttributeName: Application.greyColor,
NSKernAttributeName: 0.5,
NSParagraphStyleAttributeName: paragraphStyle
]
)
contentView.addSubview(thumbnail)
contentView.addSubview(messageView)
messageView.addSubview(messageTailIcon)
messageView.addSubview(messageLabel)
updateConstraints()
}
override func updateConstraints() {
if !didSetupConstraints {
thumbnail.autoPinEdgeToSuperviewEdge(.Top, withInset: 15)
thumbnail.autoPinEdgeToSuperviewEdge(.Leading, withInset: 8.5)
thumbnail.autoSetDimensionsToSize(CGSize(width: 35, height: 35))
messageView.autoPinEdgeToSuperviewEdge(.Top, withInset: 17.5)
messageView.autoPinEdge(.Leading, toEdge: .Trailing, ofView: thumbnail, withOffset: 10)
messageView.autoPinEdgeToSuperviewEdge(.Trailing, withInset: 24.5)
messageView.autoPinEdgeToSuperviewEdge(.Bottom)
messageTailIcon.autoPinEdgeToSuperviewEdge(.Top, withInset: 15)
messageTailIcon.autoPinEdgeToSuperviewEdge(.Leading, withInset: -10)
messageTailIcon.autoSetDimensionsToSize(CGSize(width: 18, height: 9))
messageLabel.autoPinEdgesToSuperviewEdgesWithInsets(UIEdgeInsets(top: 8.5, left: 10, bottom: 8.5, right: 5), excludingEdge: .Trailing)
messageLabel.autoPinEdgeToSuperviewEdge(.Trailing, withInset: 0, relation: .GreaterThanOrEqual)
didSetupConstraints = true
}
super.updateConstraints()
}
}
If you would like to view a sample project demonstrating the issue, I've pushed one to github
Okay, so finally locked down and easy answer, this has to do with your KERNING attributed only. watch this:
Also disregard the sizing of the red cell, this is NOT happening like this in the app, this is just a product of my screenshots being different sizes, but please do try this for yourself. Comment out the kerning and the reapply it and you'll see the same thing
with kerning with "Thomas"
without kerning with "Thomas"
with kerning with "Thomas says hello"
without kerning with "Thomas says hello"
I've done everything possible to check the code, use different constraints, and I even played around with ALL options of an NSAttributedString, and the only thing that changes this bad behavior is the kerning attribute, and it's doing this to all types of fonts, not just Avenir. In fact, the font you used in this example is system font when you didn't set a font at all, but I've tried it with 3 fonts now, same effect, the kerning seems to be broken or perhaps its working as intended for Swift and/or ObjC, but I think this is actually a bug.
Most NSAttributedString options, if you want to mess around with stuff:
var myString1 = NSMutableAttributedString(string:"Thomas asdfadsf asdfasdfasdf asdfasdf asdfasdf \n asdfasdf asdf \n")
let myString1Font1 = UIFont.systemFontOfSize(12.0)
let originalNSString = myString1.string as NSString
let myString1Range1 = originalNSString.rangeOfString(myString1.string)
var myString1ParaStyle1 = NSMutableParagraphStyle()
myString1ParaStyle1.alignment = NSTextAlignment.Natural
myString1ParaStyle1.baseWritingDirection = NSWritingDirection.Natural
myString1ParaStyle1.defaultTabInterval = 0.0
myString1ParaStyle1.firstLineHeadIndent = 0.0
myString1ParaStyle1.headIndent = 0.0
myString1ParaStyle1.hyphenationFactor = 0.0
myString1ParaStyle1.lineBreakMode = NSLineBreakMode.ByWordWrapping
myString1ParaStyle1.lineHeightMultiple = 0.0
myString1ParaStyle1.lineSpacing = 8.0
myString1ParaStyle1.maximumLineHeight = 0.0
myString1ParaStyle1.minimumLineHeight = 0.0
myString1ParaStyle1.paragraphSpacing = 0.0
myString1ParaStyle1.paragraphSpacingBefore = 0.0
myString1ParaStyle1.tailIndent = 0.0
myString1.addAttribute(NSKernAttributeName, value:0.5, range:myString1Range1)
myString1.addAttribute(NSFontAttributeName, value:myString1Font1, range:myString1Range1)
myString1.addAttribute(NSParagraphStyleAttributeName, value:myString1ParaStyle1, range:myString1Range1)
myString1.addAttribute(NSBackgroundColorAttributeName, value:UIColor.redColor(), range:myString1Range1)
myString1.addAttribute(NSForegroundColorAttributeName, value:UIColor.blackColor(), range:myString1Range1)
Again, this isn't an constraints issue, I was wrong, this is only a KERNING issue, and this sucks, but such is life, perhaps this needs to be reported to RADAR.
Also, you can try this for yourself, anything BUT a 0 or 0.00000 or as many zeros as you want will produce the wrong results with Kerning, i tried this and it messes up your label field the same way that kerning would mess up the field with a larger value:
NSKernAttributeName: 0.00000000000001
HOLD up, I solved it, from what it looks like, set this value, just add this to your paragraphStyle variable that you set up in the example project, its working with the kerning, not sure if this is working for all fonts, but it fixes your example project at least:
paragraphStyle.lineHeightMultiple = 1.5
The only problem with this method is that it works for lines with one word or one line, you'll have to do a word count adjustment to set this "lineHeightMultiple" based on when a new line appears, this sucks, but it works, obviously, not a very good method to use, but works if you have a 1 liner string, needs adjusting if you have more, otherwise just turn off kerning, and it will be solved wihout this line height multiple.
It's as if the line height is changing internally and pushing characters to a new line but apple isn't automatically accounting for this change in character width.
And as a matter of fact, I think the answer you are looking for isn't kerning at all but tracking, which will push the letters apart from each other. The problem with kerning is that kerning screws around with the glyphs of the fonts and overrides some of their behaviors and as such it can be anoticeable effect like we are seeeing here.
From Apple:
preferredFontForTextStyle:, the specific font returned includes traits
which vary according to user preferences and context, including
tracking (letter-spacing) adjustments, in addition to being tuned for
the use specified by the particular text style constant. The fonts
returned using text style constants are meant to be used for all text
in an app other than text in user interface elements, such as buttons,
bars, and labels. Naturally, you need to choose text styles that look
right in your app. It’s also important to observe the
UIContentSizeCategoryDidChangeNotification so that you can re–lay out
the text when the user changes the content size category. When your
app receives that notification, it should send the
invalidateIntrinsicContentSize message to views positioned by Auto
Layout or send setNeedsLayout to user interface elements positioned
manually. And it should invalidate preferred fonts or font descriptors
and acquire new ones as needed.
https://developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/TypoFeatures/TextSystemFeatures.html
If you truly need kerning, then you should probably be tweaking the kerning values of the ligatures if the font has any available to play with.
Other things to consider, this does work, but it's also bold so it's already not something that matches your style above, but it's something you can toy around with:
let sytemDynamicFontDescriptor = UIFontDescriptor.preferredFontDescriptorWithTextStyle(UIFontTextStyleHeadline)
let size = sytemDynamicFontDescriptor.pointSize
let myString1Font1 = UIFont(descriptor: sytemDynamicFontDescriptor, size:size)
println(sytemDynamicFontDescriptor.fontAttributes())
messageLabel.numberOfLines = 0
messageLabel.layer.cornerRadius = 10
messageLabel.attributedText = NSMutableAttributedString(
string: "Thomas asdfad as ",
// string: "Thomas says hello", // switch back to this to see it display the text properly on one
attributes: [
NSFontAttributeName: myString1Font1,
NSForegroundColorAttributeName: UIColor.blackColor(),
NSBackgroundColorAttributeName: UIColor.redColor(),
NSKernAttributeName: 0.5,
NSParagraphStyleAttributeName: paragraphStyle
]
)
I imported 2 *.ttf font files for a normal and bold font into xcode, set everything up in the .plist etc - and I can perfectly view the font in the storyboard now.
Unfortunately attributed textviews as well as labels or buttons will ignore my font when I set it in storyboard mode!
If I generate something programmatically it works fine, e.g. like this:
var testButton = UIButton()
testButton.setTitle("Abbrechen", forState: UIControlState.Normal)
testButton.backgroundColor = UIColor.blueColor()
testButton.titleLabel?.font = UIFont(name: "FaktConPro-Bold", size: 37)
testButton.tintColor = UIColor.redColor()
testButton.frame = CGRectMake(0 , 0, self.view.frame.width, 60)
view.addSubview(testButton)
any hints? does iOS prefer any format?
€dit:setting the labels and textfields to "plain" instead of "attributed" temporarily fixes the problem
This is a bug on Xcode. I already created a radar a couple of month ago. Here: http://openradar.appspot.com/radar?id=5117089870249984