[英]How to set letter spacing of UITextField
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 of UIView
?如果PinTextField
是UIView
的子类,有没有办法做到这一点? I know in a ViewController
you could use UITextFieldTextDidChangeNotification
and set the attributed text for each change.我知道在ViewController
您可以使用UITextFieldTextDidChangeNotification
并为每个更改设置属性文本。 Notifications don't seem to work in a UIView
though.通知似乎在UIView
不起作用。
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 ?另外,我想知道如果要设置UITextField
文本的字母间距,是否没有比为每次更新制作属性字符串更简单的方法?
Correct spacing:正确间距:
Wrong spacing:错误的间距:
No need to go for attributedText , which to be honest, was a mess implementing with modified spacing.不需要去attributedText ,老实说,用修改后的间距实现是一团糟。 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."每个 UITextField 都有一个名为defaultTextAttributes的属性,根据 Apple 的说法,它“返回具有默认值的文本属性字典”。 . . The Apple document also says that "this property applies the specified attributes to the entire text of the text field" Apple 文档还说“此属性将指定的属性应用于文本字段的整个文本”
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在 Swift 3.0 中回答
textfield.defaultTextAttributes.updateValue(spacing, forKey: NSKernAttributeName)
where spacing is of CGFloat type.其中间距是 CGFloat 类型。 For example 2.0例如 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)
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.然而问题仍然存在,因为不同的数字具有不同的宽度,我将回到为每个数字制作一个UITextField
。
Use the defaultTextAttributes
property of UITextField
.使用UITextField
的defaultTextAttributes
属性。 It will handle the conversion to NSAttributedString
for you and apply the attributes you set.它将为您处理到NSAttributedString
的转换并应用您设置的属性。 For example:例如:
NSMutableDictionary *attrs = [self.textField.defaultTextAttributes mutableCopy];
[attrs addEntriesFromDictionary:@{
NSKernAttributeName: @18,
NSUnderlineColorAttributeName: [UIColor grayColor],
NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle | NSUnderlinePatternDash)
}];
self.textField.defaultTextAttributes = attrs;
Not really sure about any other solution instead of using attributed string.不太确定任何其他解决方案,而不是使用属性字符串。
But for the notification part, you can set the textFields
delegate to UIView
and define below method in the view.但是对于通知部分,您可以将textFields
委托设置为UIView
并在视图中定义以下方法。
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string;
The above method is called every time the text entered in the text field changes.每次在文本字段中输入的文本更改时都会调用上述方法。
Try this code After setting the delegate to the textfield.Hope it will work.在将委托设置为文本字段后试试这个代码。希望它会起作用。
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:textField.text];
[attributedString addAttribute:NSKernAttributeName
value:@(5.4)
range:NSMakeRange(0, textField.text.length)];
textField.attributedText = attributedString;
return YES;
}
This is working fine in Swift 2.2.这在 Swift 2.2 中运行良好。 Hope this will help you for letter spacing in text field希望这对您在文本字段中的字母间距有所帮助
override func viewDidLoad() {
// Do any additional setup after loading the view.
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(SignupVC.limitTextField(_:)), name: "UITextFieldTextDidChangeNotification", object: txtContactNumber)
}
func limitTextField(Notif:NSNotification) {
let limit=10;
let attributedString = NSMutableAttributedString(string: txtContactNumber.text!)
attributedString.addAttribute(NSKernAttributeName, value: 7, range: NSMakeRange(0, (txtContactNumber.text?.characters.count)!))
// attributedString.addAttribute(NSFontAttributeName, value: font, range: NSMakeRange(0, count(textField.text)))
attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.blackColor(), range: NSMakeRange(0,(txtContactNumber.text?.characters.count)!))
txtContactNumber.attributedText = attributedString
if(txtContactNumber.text?.characters.count>limit)
{
txtContactNumber.text=txtContactNumber.text?.substringToIndex(limit)
}
}
Need to count the kern for each character and remove it for the last character.需要计算每个字符的字距并将其删除为最后一个字符。 There is example on Swift 5.3 Swift 5.3 上有示例
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let maxLength = 6
let symbolWidth = CGFloat(43)
let font = UIFont.systemFont(ofSize: 30)
if string == "" { // when user remove text
return true
}
if textField.text!.count + string.count - range.length > maxLength { // when user type extra text
return false
}
let currentText = NSMutableAttributedString(attributedString: textField.attributedText ?? NSMutableAttributedString())
currentText.deleteCharacters(in: range) // delete selected text
var newStringLength = 0
for char in string{
let newSymbol = NSMutableAttributedString(string: String(char))
newSymbol.addAttribute(.font, value: font, range: NSMakeRange(0, 1))
let currentSymbolWidth = newSymbol.size().width
let kern = symbolWidth - currentSymbolWidth
newSymbol.addAttribute(.kern, value: kern, range: NSMakeRange(0,1))
currentText.insert(newSymbol, at: range.location + newStringLength)
newStringLength += 1
}
if currentText.length == maxLength{
currentText.addAttribute(.kern, value: 0, range: NSMakeRange(maxLength - 1, 1))
}
textField.attributedText = currentText
return false
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.