在我的项目中,我们要求用户需要在文本字段中输入金额,文本字段最初应为0.00,并且用户必须输入值。数字应该从右向左移动,小数点应该始终存在。 就像用户输入1一样,它应该是0.01,如果用户输入112,它应该显示为1.12。
我可以在文本框字段中应用逗号,但我确实坚持小数点要求。我无法在文本框中输入小数点。有人可以帮我吗?
- (BOOL)textInput:(id <UITextInput>)textInput shouldChangeCharactersInRange:(NSRange)range withString:(NSString *)string {
UITextField *textField = (UITextField *)textInput;
if (textField.text.length >= MAX_LENGTH && range.length == 0)
{
return NO; // return NO to not change text
}
if (([string isEqualToString:@"0"] || [string isEqualToString:@""]) && [textField.text rangeOfString:@"."].location < range.location) {
return YES;
}
// First check whether the replacement string's numeric...
NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:@"0123456789"] invertedSet];
NSString *filtered = [[string componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:@""];
bool isNumeric = [string isEqualToString:filtered];
// Then if the replacement string's numeric, or if it's
// a backspace, or if it's a decimal point and the text
// field doesn't already contain a decimal point,
// reformat the new complete number using
// NSNumberFormatterDecimalStyle
if (isNumeric ||
[string isEqualToString:@""] ||
([string isEqualToString:@"."] &&
[textField.text rangeOfString:@"."].location == NSNotFound)) {
// Create the decimal style formatter
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
[formatter setCurrencyCode:@"USD"];
[formatter setMaximumFractionDigits:2];
// Combine the new text with the old; then remove any
// commas from the textField before formatting
NSString *combinedText = [textField.text stringByReplacingCharactersInRange:range withString:string];
NSString *numberWithoutCommas = [combinedText stringByReplacingOccurrencesOfString:@"," withString:@""];
NSNumber *number = [formatter numberFromString:numberWithoutCommas];
NSString *formattedString = [formatter stringFromNumber:number];
// If the last entry was a decimal or a zero after a decimal,
// re-add it here because the formatter will naturally remove
// it.
if ([string isEqualToString:@"."] &&
range.location == textField.text.length) {
formattedString = [formattedString stringByAppendingString:@"."];
}
textField.text = formattedString;
}
// Return no, because either the replacement string is not
// valid or it is and the textfield has already been updated
// accordingly
return NO;
}
答案 0 :(得分:1)
这是一种不同的方法。不要实现委托方法textField: shouldChangeCharactersInRange:withString:
。而是将文本字段的“编辑已更改”事件连接到视图控制器中的操作。在操作中,我们将做两件事:根据您的要求重新格式化文本,并在重新格式化过程中保留光标位置。在重新格式化之前,我们计算从文本末尾到光标位置的偏移量。重新格式化后,我们根据该偏移重置光标位置:
- (IBAction)textFieldEditingChanged:(UITextField *)textField {
int offset = [textField offsetFromPosition:textField.endOfDocument toPosition:textField.selectedTextRange.end];
textField.text = textField.text.Nitya_reformattedString;
UITextPosition *position = [textField positionFromPosition:textField.endOfDocument offset:offset];
textField.selectedTextRange = [textField textRangeFromPosition:position toPosition:position];
}
要初始化文本字段,我们可以重新格式化空字符串:
- (void)viewDidLoad {
[super viewDidLoad];
self.textField.text = @"".Nitya_reformattedString;
}
要进行重新格式化,我们会在NSString
上编写一个类别:
@interface NSString (Nitya)
- (NSString *)Nitya_reformattedString;
- (BOOL)Nitya_isDigit;
@end
@implementation NSString (Nitya)
- (NSString *)Nitya_reformattedString {
请注意,文字字段会在更新其文本后发送“已修改 ,因此文字可能包含非数字字符或实际上包含任何内容,因为用户可能已选择整个内容并粘贴其他一些字符串。所以第一步就是抛弃所有非数字字符:
NSMutableString *newString = [NSMutableString string];
[self enumerateSubstringsInRange:NSMakeRange(0, self.length) options:NSStringEnumerationByComposedCharacterSequences usingBlock:^(NSString * _Nullable substring, NSRange substringRange, NSRange enclosingRange, BOOL * _Nonnull stop) {
if (substring.Nitya_isDigit) {
[newString appendString:substring];
}
}];
请注意,我们也删除了小数点。
现在让我们定义一些描述所需格式的常量:
static const int requiredFractionalDigitCount = 2;
static const int requiredIntegerDigitCount = 1;
static const int requiredDigitCount = requiredFractionalDigitCount + requiredIntegerDigitCount;
static const int maxDigitCount = 12;
第二步是如果数字太多,则修剪字符串前面的字符:
if (newString.length > maxDigitCount) {
[newString replaceCharactersInRange:NSMakeRange(0, newString.length - maxDigitCount) withString:@""];
}
我们还希望修剪字符串中的前导零(或者从最初的“0.00”字符串中的零将保持不变并且看起来很奇怪):
while (newString.length > 0 && [newString characterAtIndex:0] == '0') {
[newString replaceCharactersInRange:NSMakeRange(0, 1) withString:@""];
}
现在我们要确保我们有足够的数字,在必要时将零放回前面:
while (newString.length < requiredDigitCount) {
[newString insertString:@"0" atIndex:0];
}
最后,我们将小数点放回:
[newString insertString:@"." atIndex:newString.length - requiredFractionalDigitCount];
return newString;
}
这是辅助方法Nitya_isDigit
:
- (BOOL)Nitya_isDigit {
static dispatch_once_t once;
static NSCharacterSet *digits;
dispatch_once(&once, ^{
digits = [NSCharacterSet characterSetWithCharactersInString:@"0123456789"];
});
return self.length == 1 && [digits characterIsMember:[self characterAtIndex:0]];
}
@end
答案 1 :(得分:0)
您可以将文本字段文本右对齐,以便从右到左获取文本。
要根据需要格式化文本,您只需执行以下操作:
最初将文本字段文本设置为0.00
#pragma text field delegate methods
-(BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
if ([textField.text isEqualToString:@"0.00"]) {
textField.text=@"";
}
_enteredString=_textField.text;
_textFieldString=[_enteredString stringByAppendingString:string];
_yourLabel.text=[self formatNumber:_textFieldString];
// you have to format this _yourLabel.text to fit into the textfield in your required format
// Else if you dont want to do additional stuff, simply put the label on top of the textfield.
return YES;
}
-(NSString *)formatNumber:(NSString *) enteredCharacter{
float enteredValue=[enteredCharacter floatValue]*0.01;
NSNumber *enteredNum=[NSNumber numberWithFloat:enteredValue];
return [enteredNum stringValue];
}
注意:确保只输入文字字段中的数字。