如何设置 UITextField 的字母间距
How to set letter spacing of UITextField
我有一个应用程序,用户必须在其中输入一个四位数的个人识别码。所有数字之间必须保持一定距离。
如果 PinTextField
是 UIView
的子类,有没有办法做到这一点?我知道在 ViewController
中您可以使用 UITextFieldTextDidChangeNotification
并为每个更改设置属性文本。不过,通知似乎在 UIView
中不起作用。
我还想知道,如果您想设置 UITextField
文本的字母间距,是否有比为每次更新创建属性字符串更简单的方法?
正确的间距:
间距错误:
不太确定除了使用属性字符串之外的任何其他解决方案。
但对于通知部分,您可以将 textFields
委托设置为 UIView
并在视图中定义以下方法。
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string;
每次在文本字段中输入的文本发生变化时都会调用上述方法。
尝试此代码将委托设置为 textfield.Hope 后它会起作用。
- (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;
}
这就是为每次更改设置紧排的最终方法
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
}
}
但是问题仍然存在,因为不同的数字有不同的宽度,我将求助于为每个数字制作一个 UITextField
。
这在 Swift 2.2 中运行良好。希望这对文本字段中的字母间距有帮助
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)
}
}
使用 UITextField
的 defaultTextAttributes
属性。它将为您处理到 NSAttributedString
的转换并应用您设置的属性。例如:
NSMutableDictionary *attrs = [self.textField.defaultTextAttributes mutableCopy];
[attrs addEntriesFromDictionary:@{
NSKernAttributeName: @18,
NSUnderlineColorAttributeName: [UIColor grayColor],
NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle | NSUnderlinePatternDash)
}];
self.textField.defaultTextAttributes = attrs;
无需选择 attributedText,老实说,修改间距后的实现一团糟。一旦我关闭键盘,间距就消失了,这促使我进一步挖掘。
每个 UITextField 都有一个 属性,称为 defaultTextAttributes,根据 Apple "returns a dictionary of text attributes with default values."。 Apple document 也表示 "this property applies the specified attributes to the entire text of the text field"
只需在您的代码中找到合适的位置,通常是初始化文本字段的位置,然后复制并粘贴以下内容。
已在 Swift 3.0
中回答
textfield.defaultTextAttributes.updateValue(spacing, forKey: NSKernAttributeName)
其中spacing是CGFloat类型的。例如 2.0
这也适用于不同的字体。
干杯!!
最新语法好像是:
yourField.defaultTextAttributes.updateValue(36.0,
forKey: NSAttributedString.Key.kern)
需要计算每个字符的紧排,并为最后一个字符删除它。 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
}
我有一个应用程序,用户必须在其中输入一个四位数的个人识别码。所有数字之间必须保持一定距离。
如果 PinTextField
是 UIView
的子类,有没有办法做到这一点?我知道在 ViewController
中您可以使用 UITextFieldTextDidChangeNotification
并为每个更改设置属性文本。不过,通知似乎在 UIView
中不起作用。
我还想知道,如果您想设置 UITextField
文本的字母间距,是否有比为每次更新创建属性字符串更简单的方法?
正确的间距:
间距错误:
不太确定除了使用属性字符串之外的任何其他解决方案。
但对于通知部分,您可以将 textFields
委托设置为 UIView
并在视图中定义以下方法。
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string;
每次在文本字段中输入的文本发生变化时都会调用上述方法。
尝试此代码将委托设置为 textfield.Hope 后它会起作用。
- (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;
}
这就是为每次更改设置紧排的最终方法
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
}
}
但是问题仍然存在,因为不同的数字有不同的宽度,我将求助于为每个数字制作一个 UITextField
。
这在 Swift 2.2 中运行良好。希望这对文本字段中的字母间距有帮助
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)
}
}
使用 UITextField
的 defaultTextAttributes
属性。它将为您处理到 NSAttributedString
的转换并应用您设置的属性。例如:
NSMutableDictionary *attrs = [self.textField.defaultTextAttributes mutableCopy];
[attrs addEntriesFromDictionary:@{
NSKernAttributeName: @18,
NSUnderlineColorAttributeName: [UIColor grayColor],
NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle | NSUnderlinePatternDash)
}];
self.textField.defaultTextAttributes = attrs;
无需选择 attributedText,老实说,修改间距后的实现一团糟。一旦我关闭键盘,间距就消失了,这促使我进一步挖掘。
每个 UITextField 都有一个 属性,称为 defaultTextAttributes,根据 Apple "returns a dictionary of text attributes with default values."。 Apple document 也表示 "this property applies the specified attributes to the entire text of the text field"
只需在您的代码中找到合适的位置,通常是初始化文本字段的位置,然后复制并粘贴以下内容。
已在 Swift 3.0
中回答textfield.defaultTextAttributes.updateValue(spacing, forKey: NSKernAttributeName)
其中spacing是CGFloat类型的。例如 2.0
这也适用于不同的字体。
干杯!!
最新语法好像是:
yourField.defaultTextAttributes.updateValue(36.0,
forKey: NSAttributedString.Key.kern)
需要计算每个字符的紧排,并为最后一个字符删除它。 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
}