How to set letter spacing of UITextField
Solution 1
No need to go for attributedText, which to be honest, was a mess implementing with modified spacing. As soon as I closed the keyboard the spacing disappeared, which prompted me to dig further.
Every UITextField has a property called defaultTextAttributes, which according to Apple "returns a dictionary of text attributes with default values.". The Apple document also says that "this property applies the specified attributes to the entire text of the text field"
Just find a suitable place in your code, usually where the textfield is being initialized and then copy and paste the following.
Answered in Swift 3.0
textfield.defaultTextAttributes.updateValue(spacing, forKey: NSKernAttributeName)
where spacing is of CGFloat type. For example 2.0
This works for different fonts as well.
Cheers!!
The latest syntax seems to be:
yourField.defaultTextAttributes.updateValue(36.0,
forKey: NSAttributedString.Key.kern)
Solution 2
This is what eventually worked to set the kern for every change
textField.addTarget(self, action: "textFieldDidChange", forControlEvents: .EditingChanged)
func textFieldDidChange () {
let attributedString = NSMutableAttributedString(string: textField.text)
attributedString.addAttribute(NSKernAttributeName, value: 5, range: NSMakeRange(0, count(textField.text)))
attributedString.addAttribute(NSFontAttributeName, value: font, range: NSMakeRange(0, count(textField.text)))
attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.blackColor(), range: NSMakeRange(0, count(textField.text)))
textField.attributedText = attributedString
}
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
if count(textField.text) < 4 {
return true
// Else if 4 and delete is allowed
}else if count(string) == 0 {
return true
// Else limit reached
}else{
return false
}
}
The problem however remains because different numbers have different widths, I will just resort back to making a UITextField
for every digit.
Solution 3
Use the defaultTextAttributes
property of UITextField
. It will handle the conversion to NSAttributedString
for you and apply the attributes you set. For example:
NSMutableDictionary *attrs = [self.textField.defaultTextAttributes mutableCopy];
[attrs addEntriesFromDictionary:@{
NSKernAttributeName: @18,
NSUnderlineColorAttributeName: [UIColor grayColor],
NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle | NSUnderlinePatternDash)
}];
self.textField.defaultTextAttributes = attrs;
KMV
Updated on July 20, 2020Comments
-
KMV almost 4 years
I have an app in which the user has to type a four digit pin code. All digits have to be at a set distance from each other.
Is there a way to do this if the
PinTextField
is a subclass ofUIView
? I know in aViewController
you could useUITextFieldTextDidChangeNotification
and set the attributed text for each change. Notifications don't seem to work in aUIView
though.Also I was wondering if there isn't a simpler way than making an attributed string for every update if you want to set the letter spacing of a
UITextField
text ?Correct spacing:
Wrong spacing:
-
KMV almost 9 years
shouldChangeCharactersInRange
does not work for the first letter though, it only appears after you have input the second one. -
Vishnuvardhan almost 9 yearscheck this link for first letter change, it may help you: stackoverflow.com/questions/7010547/…
-
Jurasic over 6 yearsThe proper solution is to use monospace font.
-
iOSer over 6 years@Fattie thank you for adding the latest syntax and for the comment as well. :)
-
Soumen almost 6 yearsIf the TextField is secure then this solution is not working.
-
iOSer almost 6 years@Soumen sorry I have been busy with projects lately. But I will definitely look into this as soon as I get time. Thank btw for pointing that out
-
Ashu over 4 yearsHow to remove space from last text. I have to only feed 4 digit. In that case it will wrong.
-
iOSer over 4 years@Ashu So you want three digits to be equally spaced and the last digit not so? Not sure what do you mean
-
Ashu over 4 years@iOSer yes, last digit should not have extra space
-
iOSer over 4 yearsThen Im afraid you'll have to use multiple texfields and take care of the spacing yourself.
-
rmp251 over 2 yearsYour entire second method can be nicely collapsed into one line: func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { string.isEmpty || count(textField.text) < 4 }