Каков наилучший способ ввода числовых значений с десятичными точками?
В моем приложении пользователи должны иметь возможность вводить числовые значения с десятичными знаками. IPhone не предоставляет клавиатуру, которая подходит для этой цели - только цифровую клавиатуру и клавиатуру с цифрами и символами.
Есть ли простой способ использовать последнее и предотвратить ввод нечетного ввода без необходимости повторного выражения конечного результата?
Спасибо!
Ответы
Ответ 1
Более элегантное решение также может быть самым простым.
Вам не нужен разделитель десятичной дроби
Почему? Потому что вы можете просто вывести его из пользовательского ввода. Например, в локали США, когда вам нужно ввести $1.23, вы начинаете с ввода чисел 1-2-3 (в этом порядке). В системе, по мере ввода каждого символа, это будет распознаваться как:
- пользователь вводит 1: $0.01
- пользователь вводит 2: $0.12
- пользователь вводит 3: $1.23
Обратите внимание, как мы определили десятичный разделитель на основе пользовательского ввода. Теперь, если пользователь хочет ввести $1.00, они просто будут вводить цифры 1-0-0.
Для того, чтобы ваш код обрабатывал валюты в разных языковых стандартах, вам нужно получить максимальные цифры в валюте. Это можно сделать с помощью следующего фрагмента кода:
NSNumberFormatter *currencyFormatter = [[NSNumberFormatter alloc] init];
[currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
int currencyScale = [currencyFormatter maximumFractionDigits];
Например, японская иена имеет цифру максимальной доли 0. Таким образом, при работе с входом йены разделитель десятичной дроби отсутствует и, следовательно, не нужно даже беспокоиться о дробных суммах.
Этот подход к проблеме позволяет использовать клавиатуру с цифровыми вводами, предоставляемую Apple, без головных болей пользовательских клавиатур, проверки правильности и т.д.
Ответ 2
Я думаю, было бы неплохо отметить, что с iOS 4.1 вы можете использовать новый UIKeyboardTypeDecimalPad
.
Итак, теперь вам просто нужно:
myTextField.keyboardType=UIKeyboardTypeDecimalPad;
Ответ 3
Вот пример решения, предложенного в принятом ответе. Это не обрабатывает другие валюты или что-то еще - в моем случае мне нужна была поддержка только долларов, независимо от того, какой язык/валюта для меня это было нормально:
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string {
double currentValue = [textField.text doubleValue];
//Replace line above with this
//double currentValue = [[textField text] substringFromIndex:1] doubleValue];
double cents = round(currentValue * 100.0f);
if ([string length]) {
for (size_t i = 0; i < [string length]; i++) {
unichar c = [string characterAtIndex:i];
if (isnumber(c)) {
cents *= 10;
cents += c - '0';
}
}
} else {
// back Space
cents = floor(cents / 10);
}
textField.text = [NSString stringWithFormat:@"%.2f", cents / 100.0f];
//Add this line
//[textField setText:[NSString stringWithFormat:@"$%@",[textField text]]];
return NO;
}
Круглые и этажи важны: а) из-за представления с плавающей запятой, иногда теряющего .00001 или что-то еще, и б) строки формата, округляющей любую точность, которую мы удалили в области backspace.
Ответ 4
Я хотел сделать то же самое, за исключением валют, а не прямых десятичных значений.
Я закончил создание пользовательского представления, которое содержит UITextField и UILabel. Этикетка охватывает текстовое поле, но текстовое поле по-прежнему получает штрихи. Я использую уведомление UITextFieldTextDidChange, чтобы наблюдать изменения в текстовом поле (и я использовал NSNumberFormatter, чтобы превратить полученный результат в форматированное значение валюты), чтобы обновить метку.
Чтобы отключить лупу, которая позволяет пользователю переместить точку вставки, вам нужно будет использовать пользовательский подкласс UITextField и переопределить касаниеBegan: withEvent: и установить его, чтобы ничего не делать.
Мое решение может отличаться от того, что вам нужно, потому что десятичная точка всегда исправлена - я использую настройку валюты системы, чтобы определить, сколько цифр должно быть после десятичной точки. Однако цифровая клавиатура на нем не имеет десятичной точки. И вы не можете добавить какие-либо кнопки на клавиатуре (что особенно усугубляет, потому что в нижнем левом углу клавиатуры есть пустая кнопка, которая идеально подходит для десятичной точки!) Поэтому у меня нет решения для этого, к сожалению.
Ответ 5
В зависимости от конкретного приложения предоставление слайдера, на котором пользователь может выбрать позицию, может быть лучшим выбором на iphone. Тогда никакие цифры не должны вводиться вообще.
Ответ 6
Вы можете использовать слайдер (как это предложил Мартин против Лёвиса) или UIPickerView с отдельным колесом для каждой из цифр.
Ответ 7
Я построил настраиваемый контроллер вида с числовой точкой с десятичной точкой... проверьте его:
http://sites.google.com/site/psychopupnet/iphone-sdk/tenkeypadcustom10-keypadwithdecimal
Ответ 8
Как и в iOS4.1, есть новый тип клавиатуры UIKeyboardTypeNumberPad, но, к сожалению, пока он не появляется в списке выбора Interface Builder.
Ответ 9
Здесь, как это сделать, не используя float, round() или ceil() в агностической форме валюты.
В вашем контроллере просмотра настройте следующие переменные экземпляра (с соответствующими операторами @property, если это ваша сумка):
@interface MyViewController : UIViewController <UITextFieldDelegate> {
@private
UITextField *firstResponder;
NSNumberFormatter *formatter;
NSInteger currencyScale;
NSString *enteredDigits;
}
@property (nonatomic, readwrite, assign) UITextField *firstResponder;
@property (nonatomic, readwrite, retain) NSNumberFormatter *formatter;
@property (nonatomic, readwrite, retain) NSString *enteredDigits;
@end
и ваш метод viewDidLoad должен содержать следующее:
- (void)viewDidLoad {
[super viewDidLoad];
NSNumberFormatter *aFormatter = [[NSNumberFormatter alloc] init];
[aFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
currencyScale = -1 * [aFormatter maximumFractionDigits];
self.formatter = aFormatter;
[aFormatter release];
}
Затем реализуйте ваши методы UITextFieldDelegate следующим образом:
#pragma mark -
#pragma mark UITextFieldDelegate methods
- (void)textFieldDidBeginEditing:(UITextField *)textField {
// Keep a pointer to the field, so we can resign it from a toolbar
self.firstResponder = textField;
self.enteredDigits = @"";
}
- (void)textFieldDidEndEditing:(UITextField *)textField {
if ([self.enteredDigits length] > 0) {
// Get the amount
NSDecimalNumber *result = [[NSDecimalNumber decimalNumberWithString:self.enteredDigits] decimalNumberByMultiplyingByPowerOf10:currencyScale];
NSLog(@"result: %@", result);
}
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
// Check the length of the string
if ([string length]) {
self.enteredDigits = [self.enteredDigits stringByAppendingFormat:@"%d", [string integerValue]];
} else {
// This is a backspace
NSUInteger len = [self.enteredDigits length];
if (len > 1) {
self.enteredDigits = [self.enteredDigits substringWithRange:NSMakeRange(0, len - 1)];
} else {
self.enteredDigits = @"";
}
}
NSDecimalNumber *decimal = nil;
if ( ![self.enteredDigits isEqualToString:@""]) {
decimal = [[NSDecimalNumber decimalNumberWithString:self.enteredDigits] decimalNumberByMultiplyingByPowerOf10:currencyScale];
} else {
decimal = [NSDecimalNumber zero];
}
// Replace the text with the localized decimal number
textField.text = [self.formatter stringFromNumber:decimal];
return NO;
}
Только проверял это с фунтами и пенсом, но он должен работать и с японской йеной. Если вы хотите форматировать десятичные знаки для невоенных целей, просто прочитайте документацию на NSNumberFormatter и установите format/maximumFractionDigits, который вы хотите.
Ответ 10
A Swift 2 реализация сообщения Майка Уэллера, а также только USD:
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
guard let str = textField.text else {
textField.text = "0.00"
return false
}
let value = (str as NSString).doubleValue
var cents = round(value * 100)
if string.characters.count > 0 {
for c in string.characters {
if let num = Int(String(c)) {
cents *= 10
cents += Double(num)
}
}
}
else {
cents = floor(cents / 10)
}
textField.text = NSString(format: "%.2f", cents/100) as String
return false
}
Ответ 11
Вы можете использовать STATextField и установить для CurrencyRepresentation значение YES, которое:
Обеспечивает ввод не более одной десятичной точки и что справа от указанной десятичной точки вводится не более двух цифр.
Там также STAATMTextField, который по умолчанию поддерживает режим валюты и текстовый ввод в банке:
Предоставляет текстовое поле, которое имитирует поведение входа в систему ATM.