2008-11-09 77 views
50

在我的应用程序中,用户需要能够输入带小数点的数字值。 iPhone不提供专门用于此目的的键盘 - 只有数字键盘和带有数字和符号的键盘。输入带小数点的数值的最佳方法是什么?

有没有简单的方法来使用后者,并防止输入任何非数字输入而不必将正则表达式正则表达式?

谢谢!

回答

49

更优雅的解决方案碰巧也是最简单的。

你并不需要一个小数点键

为什么?因为你可以简单地从用户的输入中推断出它。例如,在美国语言环境中,当您输入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的最大分数位数所以,随着日元输入打交道时,没有小数点分隔符,因此没有必要连担心分数金额。

这种方法的问题,您可以使用自定义的无键盘,正则表达式验证的头痛苹果提供的库存数字输入键盘等

+7

只是为了确保 - 不要使用浮动货币! – Svante 2009-02-24 01:16:24

+9

+1 - 使用NSDecimalNumber – shek 2009-02-25 04:40:56

+1

我也写过关于这对任何人的博客贴子,有兴趣:http://blog.weareuproar.com/?p=11 – shek 2009-03-12 03:57:06

2

根据具体的应用,提供一个滑块,用户可以选择一个位置可能是一个更好的选择在iphone上。然后根本不需要输入任何数字。

2

您可能想要为每个数字使用一个滑块(如Martin v。Löwis所建议的)或UIPickerView,并使用单独的滑轮。

3

我想做的完全一样的事情,除了货币而不是直接十进制值。

我最终创建了一个包含UITextField和UILabel的自定义视图。标签覆盖了文本字段,但文本字段仍然接收到触摸。我使用UITextFieldTextDidChange通知来观察文本字段中的更改(并且我使用NSNumberFormatter将结果数字转换为格式化的货币值)以更新标签。

要禁用允许用户重新定位插入点的放大镜,您需要使用自定义UITextField子类并覆盖touchesBegan:withEvent:并将其设置为不执行任何操作。

我的解决方案可能与您需要的不同,因为小数点总是固定的 - 我使用系统的货币设置来确定小数点后应该有多少数字。但是,数字小键盘上没有小数点。你不能在键盘上添加任何按钮(这是特别加重的,因为在键盘的左下角有一个空白按钮,这对于小数点来说是完美的!)所以我没有解决方案,不幸的是。

+0

我做了这样的事情,除了与自定义视图。当它接收到触摸时,我在屏幕底部(键盘后面)设置一个文本字段,并在其上调用“becomeFirstResponder”。那么我不需要担心禁用放大镜。 – benzado 2010-01-10 00:24:46

+0

你对光标做了什么? – drewish 2012-08-24 02:01:17

12

下面是一个例子为解决中接受的答案建议。这不处理其他货币或者任何东西 - 在我的情况下,我只需要对美元的支持,无论在什么区域/货币所以这是确定对我来说:

-(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或其他值,b)格式字符串会舍去我们在退格部分删除的任何精度。

1

由于对iOS4.1的,有一个新的键盘类型UIKeyboardTypeNumberPad,但遗憾的是,由于但它似乎并未出现在界面生成器选择列表中。

1

下面介绍如何在货币不可知的情况下使用浮动,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上的文档并设置您想要的格式/ maximumFractionDigits即可。

52

我认为应该指出,从iOS 4.1开始,您可以使用新的UIKeyboardTypeDecimalPad

所以,现在你只需要:

myTextField.keyboardType=UIKeyboardTypeDecimalPad; 
0

迅速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 
} 
0

您可以使用STATextField并设置currencyRepresentation为YES其中:

确保不会输入一个以上的小数点,并且输入不超过两位数字t的小数点。

还有STAATMTextField它默认支持货币模式 ATM文本输入:

提供的文本字段模仿ATM机输入行为。

相关问题