VENTokenField 按住退格键删除令牌
VENTokenField hold backspace key to delete tokens
在尝试允许删除多个令牌时,由于用户在 VENTokenField 中按住退格键以与本机电子邮件应用程序或消息应用程序相同,我遇到了很多问题...
首先,我只能从 VENToken 的 UITextField 子类提供的初始代码(技术上涉及私有 API)检测到一次点击退格键 - (BOOL)keyboardInputShouldDelete:(UITextField *)textField
。这很好,但对于检测退格按钮上的长按没有帮助,退格按钮仅在您实际在某个 UITextField 中有字符时有效,而不是在 UITextField 为空时(例如在我们的例子中)。
我也遇到过这个 blogpost,它提出了另一种访问更多私有 API 的方法,但是,它没有提供解决我的问题的方法。由于没有记录,我想知道是否有一种有效的方法来检测此事件?
我首先解决了它,注释掉 VENBackspaceTextField class'
中的所有内容
keyboardInputShouldDelete:(UITextField *)textField
然后,在 VENTokenField 中添加 2 个常量 header:
NSString * const kTextEmpty = @"\u200B"; // Zero-Width Space
NSString * const kTextHidden = @"\u200D"; // Zero-Width Joiner
每次令牌成为第一响应者时,确保文本字段为空文本:
- (void)inputTextFieldBecomeFirstResponder {
[self.inputTextField becomeFirstResponder];
if (self.tokens.count) {
[self.inputTextField setText:kTextEmpty];
}
...
}
并在光标不可见时将其设置为隐藏:
- (void)setCursorVisibility {
NSArray *highlightedTokens = [self.tokens filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(VENToken *evaluatedObject, NSDictionary *bindings) {
return evaluatedObject.highlighted;
}]];
BOOL visible = [highlightedTokens count] == 0;
if (visible) {
[self inputTextFieldBecomeFirstResponder];
} else {
[self.invisibleTextField becomeFirstResponder];
[self.invisibleTextField setText:kTextHidden];
}
}
然后,修改textField Delegate方法:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if (self.tokens.count && [string isEqualToString:@""] && [textField.text isEqualToString:kTextEmpty]){
VENToken *lastToken = [self.tokens lastObject];
lastToken.highlighted = YES;
[_inputTextField setText:kTextHidden];
_inputTextField.alpha = 0.0;
return NO;
}
if ([textField.text isEqualToString:kTextHidden]){
[self deleteHighlighted];
[self unhighlightAllTokens];
return (![string isEqualToString:@""]);
}
//If there are any highlighted tokens, delete
[self deleteHighlighted];
return YES;
}
在尝试允许删除多个令牌时,由于用户在 VENTokenField 中按住退格键以与本机电子邮件应用程序或消息应用程序相同,我遇到了很多问题...
首先,我只能从 VENToken 的 UITextField 子类提供的初始代码(技术上涉及私有 API)检测到一次点击退格键 - (BOOL)keyboardInputShouldDelete:(UITextField *)textField
。这很好,但对于检测退格按钮上的长按没有帮助,退格按钮仅在您实际在某个 UITextField 中有字符时有效,而不是在 UITextField 为空时(例如在我们的例子中)。
我也遇到过这个 blogpost,它提出了另一种访问更多私有 API 的方法,但是,它没有提供解决我的问题的方法。由于没有记录,我想知道是否有一种有效的方法来检测此事件?
我首先解决了它,注释掉 VENBackspaceTextField class'
中的所有内容keyboardInputShouldDelete:(UITextField *)textField
然后,在 VENTokenField 中添加 2 个常量 header:
NSString * const kTextEmpty = @"\u200B"; // Zero-Width Space
NSString * const kTextHidden = @"\u200D"; // Zero-Width Joiner
每次令牌成为第一响应者时,确保文本字段为空文本:
- (void)inputTextFieldBecomeFirstResponder {
[self.inputTextField becomeFirstResponder];
if (self.tokens.count) {
[self.inputTextField setText:kTextEmpty];
}
...
}
并在光标不可见时将其设置为隐藏:
- (void)setCursorVisibility {
NSArray *highlightedTokens = [self.tokens filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(VENToken *evaluatedObject, NSDictionary *bindings) {
return evaluatedObject.highlighted;
}]];
BOOL visible = [highlightedTokens count] == 0;
if (visible) {
[self inputTextFieldBecomeFirstResponder];
} else {
[self.invisibleTextField becomeFirstResponder];
[self.invisibleTextField setText:kTextHidden];
}
}
然后,修改textField Delegate方法:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if (self.tokens.count && [string isEqualToString:@""] && [textField.text isEqualToString:kTextEmpty]){
VENToken *lastToken = [self.tokens lastObject];
lastToken.highlighted = YES;
[_inputTextField setText:kTextHidden];
_inputTextField.alpha = 0.0;
return NO;
}
if ([textField.text isEqualToString:kTextHidden]){
[self deleteHighlighted];
[self unhighlightAllTokens];
return (![string isEqualToString:@""]);
}
//If there are any highlighted tokens, delete
[self deleteHighlighted];
return YES;
}