如何实现占位符文本在 UITextField 中逐字符消失
How to achieve that placeholder text disappears character by character in UITextField
你能帮帮我吗
在 UITextField
中,当我们提供占位符文本时,当我们输入任何字符时,其占位符字符串将消失。我怎样才能实现只输入的字符而不是完整的字符串?这意味着如果我输入 3 个字符,只有占位符的前 3 个字符会消失。
#编辑 1
另外,新输入的字符文字颜色会发生变化,其余字符文字颜色保持不变。
提前致谢。
否 如果在 UITextfield 上创建自定义层后,您将无法执行此操作,您需要检查输入的字符是否与占位符字符串匹配,然后只会替换该字符。
另见
我的解决方案是使用 UITextField 文本 属性
+(BOOL)shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string
textField:(UITextField *)textField
mask:(NSString *)mask withMaskTemplate:(NSString *)maskTemplate{
NSString * alreadyExistString = @"";
if (string.length == 0) {
alreadyExistString = textField.text;
for (int i = range.location; i >= 0; i--) {
unichar currentCharMask = [maskTemplate characterAtIndex:i];
unichar currentChar = [alreadyExistString characterAtIndex:i];
if (currentCharMask == currentChar) {// fixed value and _
continue;
}else{
alreadyExistString = [alreadyExistString stringByReplacingCharactersInRange:NSMakeRange(i, 1) withString:@"_"];
break;
}
}
textField.text = alreadyExistString;
return NO;
}else{
alreadyExistString = [textField.text stringByReplacingCharactersInRange:NSMakeRange(range.location, 1) withString:string];
}
NSMutableString * validText = [[NSMutableString alloc] init];
int last = 0;
BOOL append = NO;
for (int i = 0; i < alreadyExistString.length; i++) {
unichar currentCharMask = [mask characterAtIndex:i];
unichar currentChar = [alreadyExistString characterAtIndex:i];
BOOL isLetter = [[NSCharacterSet alphanumericCharacterSet] characterIsMember: currentChar];
BOOL isDigit = [[NSCharacterSet decimalDigitCharacterSet] characterIsMember: currentChar];
if ((isLetter && currentCharMask == '#') || (isDigit && currentCharMask == '9')) {
[validText appendString:[NSString stringWithFormat:@"%c",currentChar]];
}else{
if (currentCharMask == '#' || currentCharMask == '9') {
break;
}
if ((isLetter && currentCharMask!= currentChar)|| (isDigit && currentCharMask!= currentChar)) {
append = YES;
}
[validText appendString:[NSString stringWithFormat:@"%c",currentCharMask]];
}
last = i;
}
for (int i = last+1; i < mask.length; i++) {
unichar currentCharMask = [mask characterAtIndex:i];
if (currentCharMask != '#' && currentCharMask != '9') {
[validText appendString:[NSString stringWithFormat:@"%c",currentCharMask]];
}
if (currentCharMask == '#' || currentCharMask == '9') {
break;
}
}
if (append) {
[validText appendString:string];
}
NSString *placeHolderMask = textField.text;
NSString *sub = [validText substringWithRange:NSMakeRange(range.location, 1)];
placeHolderMask = [placeHolderMask stringByReplacingCharactersInRange:NSMakeRange(range.location, 1) withString:sub];
textField.text = placeHolderMask;
return NO;
}
@property (nonatomic,strong) NSString * maskTemplate;// like: _2_-__-__A
@property (nonatomic,strong) NSString * mask;// like: #2#-99-##A
- 最初将文本字段文本设置为屏蔽模板
- 然后当用户输入时调用 shouldChangeCharactersInRange 并且它做得很好
#编辑 1
我还实现了一些代码,将光标移动到下划线位置。如果有人需要帮助。请评论我会帮助你
#编辑2
我在使用此方法时遇到的问题
- 无法更改单个文本颜色。对于像@"_" 下划线这样的字符串和具有相同颜色的输入字符,颜色将相同。
- 如果用户未提供任何输入,那么我必须提供支票以将空白作为字符串发送。
- 跟踪个人输入。
谢谢,
仍在等待是否有任何其他使用占位符字符串的解决方法。
不使用占位符文本,而是在文本字段下方使用 UILabel 并为两者提供相同的字体样式。标签文字应该是
像“- - - - -”
并且当用户开始在文本字段上输入时,在每个字符按下后给出一个 space。
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if textField.text?.characters.count == 0 && string.characters.count != 0 {
textField.text = textField.text! + " "
}
else {
return false
}
if textField.text?.characters.count == 1 && string.characters.count != 0 {
textField.text = textField.text! + " "
}
else {
return false
}
if textField.text?.characters.count == 2 && string.characters.count != 0 {
textField.text = textField.text! + " "
}
else {
return false
}
if textField.text?.characters.count == 3 && string.characters.count != 0 {
textField.text = textField.text! + " "
}
else {
return false
}
return true
}
对于这种情况,请使用 swift 中的属性字符串,如下所示,
let attributeFontSaySomething : [String : Any] = [NSFontAttributeName : UIFont.systemFont(ofSize: 12.0)]
let attributeColorSaySomething : [String : Any] = [NSForegroundColorAttributeName : UIColor.blue]
var attributes = attributeFontSaySomething
for (key, value) in attributeColorSaySomething {
attributes(value, forKey: key)
}
let attStringSaySomething = NSAttributedString(string: "Say something", attributes: attributes)
我想这正是您要找的。使用文本 _2_-__-__A
(不是占位符文本)创建 UITextField
对象。然后,将其视图控制器用作委托,并将其添加到视图控制器:
-(BOOL)textField:(UITextField*)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString*)string{
if (range.length>1) return NO; // Avoids removing multiple characters at once
if (range.location==1) range.location++; // '2' index
if (range.location==3) range.location++; // '-' index
if (range.location==6) range.location++; // '-' index
if (range.location==9) return NO; // 'A' index
if (range.location==10) return NO; // String end
if ([string isEqualToString:@""]) return NO; //Avoids removing characters
if (range.length==0) {
range.length++;
UITextPosition *beginning = textField.beginningOfDocument;
UITextPosition *start = [textField positionFromPosition:beginning offset:range.location];
UITextPosition *end = [textField positionFromPosition:start offset:range.length];
UITextRange *textRange = [textField textRangeFromPosition:start toPosition:end];
[textField setSelectedTextRange:textRange];
}
return YES;
}
-(void)textFieldDidBeginEditing:(UITextField*)textField{
UITextPosition *beginning = textField.beginningOfDocument;
UITextPosition *start = [textField positionFromPosition:beginning offset:0];
UITextPosition *end = [textField positionFromPosition:start offset:0];
UITextRange *textRange = [textField textRangeFromPosition:start toPosition:end];
[textField setSelectedTextRange:textRange];
}
-(BOOL)textFieldShouldReturn:(UITextField*)textField{
[passwordInput resignFirstResponder];
return YES;
}
它应该按预期工作。
我不认为占位符的默认行为是可编辑的,但您可以使用 NSAttributedString
模拟占位符值来完成您想要完成的工作。
我确定这可以优化,但我在这里创建了一个处理程序 class 作为给定 UITextField
的委托,操纵用户输入的字符串以实现所需影响。您使用所需的占位符字符串初始化处理程序,因此您可以使任何文本字段以这种方式工作。
import UIKit
class CustomPlaceholderTextFieldHandler: NSObject {
let placeholderText: String
let placeholderAttributes = [NSForegroundColorAttributeName : UIColor.lightGray]
let inputAttributes = [NSForegroundColorAttributeName : UIColor(red: 255/255, green: 153/255, blue: 0, alpha: 1.0)]
var input = ""
init(placeholder: String) {
self.placeholderText = placeholder
super.init()
}
func resetPlaceholder(for textField: UITextField) {
input = ""
setCombinedText(for: textField)
}
fileprivate func setCursorPosition(for textField: UITextField) {
guard let cursorPosition = textField.position(from: textField.beginningOfDocument, offset: input.characters.count)
else { return }
textField.selectedTextRange = textField.textRange(from: cursorPosition, to: cursorPosition)
}
fileprivate func setCombinedText(for textField: UITextField) {
let placeholderSubstring = placeholderText.substring(from: input.endIndex)
let attributedString = NSMutableAttributedString(string: input + placeholderSubstring, attributes: placeholderAttributes)
attributedString.addAttributes(inputAttributes, range: NSMakeRange(0, input.characters.count))
textField.attributedText = attributedString
}
}
extension CustomPlaceholderTextFieldHandler: UITextFieldDelegate {
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if string == "" {
if input.characters.count > 0 {
input = input.substring(to: input.index(before: input.endIndex))
}
} else {
input += string
}
if input.characters.count <= placeholderText.characters.count {
setCombinedText(for: textField)
setCursorPosition(for: textField)
return false
}
return true
}
func textFieldDidBeginEditing(_ textField: UITextField) {
setCursorPosition(for: textField)
}
}
以上是我初始化 gif 的方法:
class ViewController: UIViewController {
@IBOutlet weak var textField: UITextField!
let placeholderHandler = CustomPlaceholderTextFieldHandler(placeholder: "_2_-__-__A")
override func viewDidLoad() {
super.viewDidLoad()
textField.delegate = placeholderHandler
placeholderHandler.resetPlaceholder(for: textField)
}
}
这可以扩展为在初始化时获取颜色参数、字体等,或者您可能会发现 subclass UITextField
并使其成为自己的委托更清晰。我还没有真正测试过 selecting/deleting/replacing 多个字符。
input
变量将 return 用户在任何给定点输入的文本。此外,使用固定宽度的字体会消除用户键入时的抖动并替换占位符文本。
你能帮帮我吗
在 UITextField
中,当我们提供占位符文本时,当我们输入任何字符时,其占位符字符串将消失。我怎样才能实现只输入的字符而不是完整的字符串?这意味着如果我输入 3 个字符,只有占位符的前 3 个字符会消失。
#编辑 1
另外,新输入的字符文字颜色会发生变化,其余字符文字颜色保持不变。
提前致谢。
否 如果在 UITextfield 上创建自定义层后,您将无法执行此操作,您需要检查输入的字符是否与占位符字符串匹配,然后只会替换该字符。
另见
我的解决方案是使用 UITextField 文本 属性
+(BOOL)shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string
textField:(UITextField *)textField
mask:(NSString *)mask withMaskTemplate:(NSString *)maskTemplate{
NSString * alreadyExistString = @"";
if (string.length == 0) {
alreadyExistString = textField.text;
for (int i = range.location; i >= 0; i--) {
unichar currentCharMask = [maskTemplate characterAtIndex:i];
unichar currentChar = [alreadyExistString characterAtIndex:i];
if (currentCharMask == currentChar) {// fixed value and _
continue;
}else{
alreadyExistString = [alreadyExistString stringByReplacingCharactersInRange:NSMakeRange(i, 1) withString:@"_"];
break;
}
}
textField.text = alreadyExistString;
return NO;
}else{
alreadyExistString = [textField.text stringByReplacingCharactersInRange:NSMakeRange(range.location, 1) withString:string];
}
NSMutableString * validText = [[NSMutableString alloc] init];
int last = 0;
BOOL append = NO;
for (int i = 0; i < alreadyExistString.length; i++) {
unichar currentCharMask = [mask characterAtIndex:i];
unichar currentChar = [alreadyExistString characterAtIndex:i];
BOOL isLetter = [[NSCharacterSet alphanumericCharacterSet] characterIsMember: currentChar];
BOOL isDigit = [[NSCharacterSet decimalDigitCharacterSet] characterIsMember: currentChar];
if ((isLetter && currentCharMask == '#') || (isDigit && currentCharMask == '9')) {
[validText appendString:[NSString stringWithFormat:@"%c",currentChar]];
}else{
if (currentCharMask == '#' || currentCharMask == '9') {
break;
}
if ((isLetter && currentCharMask!= currentChar)|| (isDigit && currentCharMask!= currentChar)) {
append = YES;
}
[validText appendString:[NSString stringWithFormat:@"%c",currentCharMask]];
}
last = i;
}
for (int i = last+1; i < mask.length; i++) {
unichar currentCharMask = [mask characterAtIndex:i];
if (currentCharMask != '#' && currentCharMask != '9') {
[validText appendString:[NSString stringWithFormat:@"%c",currentCharMask]];
}
if (currentCharMask == '#' || currentCharMask == '9') {
break;
}
}
if (append) {
[validText appendString:string];
}
NSString *placeHolderMask = textField.text;
NSString *sub = [validText substringWithRange:NSMakeRange(range.location, 1)];
placeHolderMask = [placeHolderMask stringByReplacingCharactersInRange:NSMakeRange(range.location, 1) withString:sub];
textField.text = placeHolderMask;
return NO;
}
@property (nonatomic,strong) NSString * maskTemplate;// like: _2_-__-__A
@property (nonatomic,strong) NSString * mask;// like: #2#-99-##A
- 最初将文本字段文本设置为屏蔽模板
- 然后当用户输入时调用 shouldChangeCharactersInRange 并且它做得很好
#编辑 1 我还实现了一些代码,将光标移动到下划线位置。如果有人需要帮助。请评论我会帮助你
#编辑2
我在使用此方法时遇到的问题
- 无法更改单个文本颜色。对于像@"_" 下划线这样的字符串和具有相同颜色的输入字符,颜色将相同。
- 如果用户未提供任何输入,那么我必须提供支票以将空白作为字符串发送。
- 跟踪个人输入。
谢谢, 仍在等待是否有任何其他使用占位符字符串的解决方法。
不使用占位符文本,而是在文本字段下方使用 UILabel 并为两者提供相同的字体样式。标签文字应该是 像“- - - - -”
并且当用户开始在文本字段上输入时,在每个字符按下后给出一个 space。
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if textField.text?.characters.count == 0 && string.characters.count != 0 {
textField.text = textField.text! + " "
}
else {
return false
}
if textField.text?.characters.count == 1 && string.characters.count != 0 {
textField.text = textField.text! + " "
}
else {
return false
}
if textField.text?.characters.count == 2 && string.characters.count != 0 {
textField.text = textField.text! + " "
}
else {
return false
}
if textField.text?.characters.count == 3 && string.characters.count != 0 {
textField.text = textField.text! + " "
}
else {
return false
}
return true
}
对于这种情况,请使用 swift 中的属性字符串,如下所示,
let attributeFontSaySomething : [String : Any] = [NSFontAttributeName : UIFont.systemFont(ofSize: 12.0)]
let attributeColorSaySomething : [String : Any] = [NSForegroundColorAttributeName : UIColor.blue]
var attributes = attributeFontSaySomething
for (key, value) in attributeColorSaySomething {
attributes(value, forKey: key)
}
let attStringSaySomething = NSAttributedString(string: "Say something", attributes: attributes)
我想这正是您要找的。使用文本 _2_-__-__A
(不是占位符文本)创建 UITextField
对象。然后,将其视图控制器用作委托,并将其添加到视图控制器:
-(BOOL)textField:(UITextField*)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString*)string{
if (range.length>1) return NO; // Avoids removing multiple characters at once
if (range.location==1) range.location++; // '2' index
if (range.location==3) range.location++; // '-' index
if (range.location==6) range.location++; // '-' index
if (range.location==9) return NO; // 'A' index
if (range.location==10) return NO; // String end
if ([string isEqualToString:@""]) return NO; //Avoids removing characters
if (range.length==0) {
range.length++;
UITextPosition *beginning = textField.beginningOfDocument;
UITextPosition *start = [textField positionFromPosition:beginning offset:range.location];
UITextPosition *end = [textField positionFromPosition:start offset:range.length];
UITextRange *textRange = [textField textRangeFromPosition:start toPosition:end];
[textField setSelectedTextRange:textRange];
}
return YES;
}
-(void)textFieldDidBeginEditing:(UITextField*)textField{
UITextPosition *beginning = textField.beginningOfDocument;
UITextPosition *start = [textField positionFromPosition:beginning offset:0];
UITextPosition *end = [textField positionFromPosition:start offset:0];
UITextRange *textRange = [textField textRangeFromPosition:start toPosition:end];
[textField setSelectedTextRange:textRange];
}
-(BOOL)textFieldShouldReturn:(UITextField*)textField{
[passwordInput resignFirstResponder];
return YES;
}
它应该按预期工作。
我不认为占位符的默认行为是可编辑的,但您可以使用 NSAttributedString
模拟占位符值来完成您想要完成的工作。
我确定这可以优化,但我在这里创建了一个处理程序 class 作为给定 UITextField
的委托,操纵用户输入的字符串以实现所需影响。您使用所需的占位符字符串初始化处理程序,因此您可以使任何文本字段以这种方式工作。
import UIKit
class CustomPlaceholderTextFieldHandler: NSObject {
let placeholderText: String
let placeholderAttributes = [NSForegroundColorAttributeName : UIColor.lightGray]
let inputAttributes = [NSForegroundColorAttributeName : UIColor(red: 255/255, green: 153/255, blue: 0, alpha: 1.0)]
var input = ""
init(placeholder: String) {
self.placeholderText = placeholder
super.init()
}
func resetPlaceholder(for textField: UITextField) {
input = ""
setCombinedText(for: textField)
}
fileprivate func setCursorPosition(for textField: UITextField) {
guard let cursorPosition = textField.position(from: textField.beginningOfDocument, offset: input.characters.count)
else { return }
textField.selectedTextRange = textField.textRange(from: cursorPosition, to: cursorPosition)
}
fileprivate func setCombinedText(for textField: UITextField) {
let placeholderSubstring = placeholderText.substring(from: input.endIndex)
let attributedString = NSMutableAttributedString(string: input + placeholderSubstring, attributes: placeholderAttributes)
attributedString.addAttributes(inputAttributes, range: NSMakeRange(0, input.characters.count))
textField.attributedText = attributedString
}
}
extension CustomPlaceholderTextFieldHandler: UITextFieldDelegate {
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if string == "" {
if input.characters.count > 0 {
input = input.substring(to: input.index(before: input.endIndex))
}
} else {
input += string
}
if input.characters.count <= placeholderText.characters.count {
setCombinedText(for: textField)
setCursorPosition(for: textField)
return false
}
return true
}
func textFieldDidBeginEditing(_ textField: UITextField) {
setCursorPosition(for: textField)
}
}
以上是我初始化 gif 的方法:
class ViewController: UIViewController {
@IBOutlet weak var textField: UITextField!
let placeholderHandler = CustomPlaceholderTextFieldHandler(placeholder: "_2_-__-__A")
override func viewDidLoad() {
super.viewDidLoad()
textField.delegate = placeholderHandler
placeholderHandler.resetPlaceholder(for: textField)
}
}
这可以扩展为在初始化时获取颜色参数、字体等,或者您可能会发现 subclass UITextField
并使其成为自己的委托更清晰。我还没有真正测试过 selecting/deleting/replacing 多个字符。
input
变量将 return 用户在任何给定点输入的文本。此外,使用固定宽度的字体会消除用户键入时的抖动并替换占位符文本。