如何实现占位符文本在UITextField中逐个字符地消失

问题描述:

您能否帮助我。如何实现占位符文本在UITextField中逐个字符地消失

UITextField当我们提供占位符文本时,其占位符字符串将在我们输入任何字符时消失。我怎样才能实现只有输入的字符将不会完整的字符串?这意味着如果我输入3个字符,则只有占位符的前3个字符将会消失。

enter image description here

#EDIT 1

此外,新输入的字符文本的颜色会改变,其他剩余的字符文本颜色保持不变。

在此先感谢。

+1

不需要占位符,创建覆盖和设置相同的文本文件的边界,基于文本字段它会自动隐藏 –

+0

雅...这是一个技巧,但我想通过重写默认的占位符属性来实现代码。谢谢。 – Vishal16

+0

@ Anbu.Karthik其实你的解决方案不工作时,我想,以取代“_”下划线与像“A”或“10”的特定字符再有就是在字符串中的不匹配。 – Vishal16

我不相信占位符的默认行为是可编辑的,但您试图完成的操作可以使用NSAttributedString来模拟占位符值。

我确定这可以优化,但是在这里我创建了一个处理程序类,作为给定UITextField的委托,处理用户输入的字符串以实现所需的效果。你用你想要的占位符字符串初始化处理程序,这样你就可以使任何文本字段以这种方式工作。

Custom Placeholder Text Field

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变量将返回用户在任何给定点输入的文本。此外,使用固定宽度的字体将消除用户输入和替换占位符文本时的不稳定性。

+0

伟大的工作。谢谢 – Vishal16

否你不能在UITextfield上创建一个自定义图层后做这个工作,因为你需要检查输入的字符与placehoder字符串是否匹配,那么只有替换字符。 也Replacing character after each type in UITextField?

+0

好的。我会尝试但我想要替换占位符个别文本。当我们输入任何输入字符时,您可以看到完整的占位符字符串消失了。我想覆盖它的默认行为。 – Vishal16

+0

好吧,我正在做一个演示请等待,如果可以的话,我还原你。 –

有使用的UITextField text属性

当用户进入输入shouldChangeCharactersInRange调用
+(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 
  • 最初设置文本字段中的文本,以掩盖模板
  • 然后我的解决方案,它做了伟大的工作,看

#编辑1 我还实现了一些将光标移动到下划线位置的代码。如果有人需要帮助。请评论我会帮你。我一直在使用面向

#Edit 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 
} 
+0

好的。好的解决方案,但我正在等待更多的回应,但如果没有其他方式来做这件事情。我会接受你的回答 – Vishal16

+0

快乐编码曼:) – Saranjith

对于像波纹管迅速这种情况下使用属性串,

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) 
+0

没有解决方案归因当我们输入任何输入时,PlacholderString将会消失。 – Vishal16

我想这就是你要找的。使用文本_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; 
} 

它应该工作打算。