用小数点input数值的最佳方法是什么?
在我的应用程序用户需要能够input小数位数字值。 iPhone不提供专门用于此目的的键盘 – 只有数字键盘和带有数字和符号的键盘。
有没有简单的方法来使用后者,并防止input任何非数字input,而不必正则expression最终结果?
谢谢!
更优雅的解决scheme也是最简单的。
您不需要小数点分隔键
为什么? 因为你可以简单地从用户的input中推断出来。 例如,在美国地区,当您input1.23美元时,首先input1-2-3(按此顺序)。 在系统中,当input每个字符时,这将被识别为:
- 用户input1:$ 0.01
- 用户input2:$ 0.12
- 用户input3:$ 1.23
注意我们如何根据用户的input推断出小数点分隔符。 现在,如果用户想要input$ 1.00,他们只需input1-0-0。
为了使您的代码处理不同区域设置的货币,您需要获取货币的最大分数位数。 这可以通过下面的代码片段完成:
NSNumberFormatter *currencyFormatter = [[NSNumberFormatter alloc] init]; [currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle]; int currencyScale = [currencyFormatter maximumFractionDigits];
例如,日元的最高分数为0.因此,在处理日元input时,没有小数点分隔,因此不必担心分数。
这个问题的方法可以让你使用Apple提供的股票数字input键盘,而不用担心自定义小键盘,正则expression式validation等问题。
我认为从iOS 4.1开始可以使用新的UIKeyboardTypeDecimalPad
。
所以现在你只需要:
myTextField.keyboardType=UIKeyboardTypeDecimalPad;
以下是接受的答案中提出的解决scheme示例。 这不处理其他货币或任何东西 – 在我的情况下,我只需要支持美元,不pipe什么区域/货币,所以这对我来说是好的:
-(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; }
轮和底是重要的a)由于浮点表示有时会丢失.00001或其他任何内容,b)格式化string会舍去我们在退格部分删除的任何精度。
我想做的是完全一样的东西,除了货币,而不是直接的十进制值。
我最终创build了一个包含UITextField和UILabel的自定义视图。 标签覆盖文本字段,但文本字段仍然接收到触摸。 我使用UITextFieldTextDidChange通知来观察文本字段中的更改(并使用NSNumberFormatter将结果数字转换为格式化的货币值)以更新标签。
要禁用允许用户重新定位插入点的放大镜,您需要使用自定义的UITextField子类,并覆盖touchesBegan:withEvent:并将其设置为不执行任何操作。
我的解决scheme可能会与您所需要的不同,因为小数点总是固定的 – 我使用系统的货币设置来确定小数点后应该有多less数字。 但是,数字小键盘上没有小数点。 而且你不能在键盘上添加任何button(这是特别加重的,因为在键盘的左下angular有一个空白的button,这将是完美的小数点!)所以我没有一个解决scheme,不幸的是。
根据特定的应用程序,提供一个滑块,用户可以select一个位置可能是一个更好的select在iPhone上。 那么根本不需要input任何数字。
您可能需要使用滑块(如Martin v。L ?wis所build议的)或UIPickerView,每个数字都有一个单独的滚轮。
我build立了一个自定义的数字键盘视图控制器的小数点…检查出来:
http://sites.google.com/site/psychopupnet/iphone-sdk/tenkeypadcustom10-keypadwithdecimal
从iOS4.1开始,有一个新的键盘typesUIKeyboardTypeNumberPad,但不幸的是,至今它似乎并没有出现在Interface Builder的select列表中。
以下是如何在货币不可知的情况下使用浮动,round()或ceil()方法。
在你的视图控制器中,设置下面的实例variables(如果这是你的包,则使用相关的@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; }
只用磅和便士来testing,但它也应该和日元一起工作。 如果您想为非货币目的格式化小数,那么只需阅读NSNumberFormatter上的文档并设置任何您想要的format / maximumFractionDigits即可。
迈克·韦勒(Mike Weller)的postSwift 2实现,也只有美元:
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 }
您可以使用STATextField并将currencyRepresentation设置为YES,其中:
确保input的小数点不超过一位,小数点右边不能超过2位。
还有STAATMTextField ,默认支持货币模式和 ATM文本input:
提供模拟ATM机器input行为的文本字段。