如何实现占位符文本在 UITextField 中逐个字符消失
Posted
技术标签:
【中文标题】如何实现占位符文本在 UITextField 中逐个字符消失【英文标题】:How to achieve that placeholder text disappears character by character in UITextField 【发布时间】:2018-02-13 09:00:41 【问题描述】:你能帮帮我吗?
在UITextField
中,当我们提供占位符文本时,当我们输入任何字符时,其占位符字符串将消失。如何实现仅输入的字符将消失而不是完整的字符串?这意味着如果我输入 3 个字符,则只有占位符的前 3 个字符会消失。
#EDIT 1
另外,新输入的字符文本颜色会改变,其他剩余字符文本颜色保持不变。
提前致谢。
【问题讨论】:
不需要占位符,创建覆盖并设置文本文件的相同边界,基于它自动隐藏的文本字段字符 Ya ... 这是一个技巧,但我想通过覆盖默认占位符属性来实现使用代码。谢谢。 @Anbu.Karthik 实际上,您的解决方案不起作用当我想用特定字符(如 'A' 或 '10' 替换 '_' 下划线时,字符串中存在不匹配。跨度> 我猜你必须用覆盖来做到这一点。 @Anbu.Karthik 是真的。 _(下划线)你需要根据输入字符串计算用户给定的输入 【参考方案1】:我不相信占位符的默认行为是可编辑的,但是您可以使用NSAttributedString
模拟占位符值来完成您想要完成的工作。
我确信这可以进行优化,但在这里我创建了一个处理程序类,它充当给定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)
这可以扩展为在初始化时采用颜色参数、字体等,或者您可能会发现它更干净地继承UITextField
并使其成为自己的委托。我还没有真正测试过这个选择/删除/替换多个字符。
input
变量将返回用户在任何给定点输入的文本。此外,使用固定宽度的字体可以消除用户键入时的抖动并替换占位符文本。
【讨论】:
【参考方案2】:不要使用占位符文本,而是在文本字段下方使用 UILabel 并为两者提供相同的字体样式。标签文本应该是 比如“- - - - -”
当用户开始在文本字段上输入时,在每个字符按下后给一个空格。
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
【讨论】:
好的。不错的解决方案,但我正在等待更多回复,但如果没有其他方法可以做到这一点。我会接受你的回答【参考方案3】:我的解决方案是使用 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
使用这种方法我遇到的问题
无法更改单个文本颜色。 @"_" 下划线和输入字符的颜色相同。 如果用户不提供任何输入,那么我必须提供检查以将空白作为字符串发送。 跟踪单个输入。谢谢, 仍在等待是否有任何其他使用占位符字符串的解决方法。
【讨论】:
请添加完整的程序。 (创建一个有名字的类并在代码中实现)。【参考方案4】:我想这正是您正在寻找的。使用文本 _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;
它应该按预期工作。
【讨论】:
【参考方案5】:对于这种情况,请像下面这样快速使用属性字符串,
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)
【讨论】:
当我们输入任何输入时,attributePlacholderString 不会消失。【参考方案6】:不,如果在 UITextfield 上创建自定义层后,您将无法执行此操作,您需要检查输入的字符是否与占位符字符串匹配,然后只会替换该字符。 另见Replacing character after each type in UITextField?
【讨论】:
好的。我会尝试,但我想替换占位符的单个文本。您可以看到当我们输入任何输入字符时,完整的占位符字符串已经消失了。我想覆盖它的默认行为。 好的,我正在做一个演示,请稍候,如果可以的话,我会回复你。以上是关于如何实现占位符文本在 UITextField 中逐个字符消失的主要内容,如果未能解决你的问题,请参考以下文章
如何调整 UITextField 占位符文本以适合 UITextField 宽度?
如何使用左侧的占位符和右侧的编辑文本创建 UITextField?