输入带小数点的数值的最佳方法是什么?

时间:2008-11-09 19:51:48

标签: iphone cocoa-touch

在我的应用中,用户需要能够输入带小数位的数值。 iPhone没有提供专门用于此目的的键盘 - 只有数字键盘和带数字和符号的键盘。

是否有一种简单的方法可以使用后者并防止输入任何非数字输入而无需正则表达式最终结果?

谢谢!

11 个答案:

答案 0 :(得分:53)

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

所以现在你必须:

myTextField.keyboardType=UIKeyboardTypeDecimalPad;

答案 1 :(得分: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.因此,在处理日元输入时,没有小数分隔符,因此无需担心分数。

这种解决问题的方法允许您使用Apple提供的库存数字输入键盘,而不会出现自定义键盘,正则表达式验证等问题。

答案 2 :(得分: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;
}

圆和层是重要的a)因为浮点表示有时会丢失.00001或其他任何东西b)格式字符串会舍入我们在退格部分中删除的任何精度。

答案 3 :(得分:3)

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

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

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

我的解决方案可能与您需要的不同,因为小数点始终是固定的 - 我使用系统的货币设置来确定小数点后应该有多少个数字。但是,数字小键盘上没有小数点。并且你不能在键盘上添加任何按钮(这尤其令人恼火,因为键盘的左下角有一个空白按钮,非常适合小数点!)所以我没有解决方案,不幸的是。

答案 4 :(得分:2)

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

答案 5 :(得分:2)

你可能想要使用一个滑块(如Martinv.Löwis所建议的)或UIPickerView,每个数字都有一个单独的轮子。​​

答案 6 :(得分:2)

我构建了一个带小数点的自定义数字键盘视图控制器...检查出来:

http://sites.google.com/site/psychopupnet/iphone-sdk/tenkeypadcustom10-keypadwithdecimal

答案 7 :(得分:1)

从iOS4.1开始,有一种新的键盘类型UIKeyboardTypeNumberPad,但不幸的是,它似乎没有出现在Interface Builder选择列表中。

答案 8 :(得分: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。

答案 9 :(得分:0)

Mike Weller的帖子的Swift 2实现,也只有USD:

Thu, 24 Sep 2015 05:49:50 +0300
From: please-change-me-at-config-initializers-devise@example.com
Reply-To: please-change-me-at-config-initializers-devise@example.com
To: ...@gmail.com
Message-ID: <560364ce3f3d_34372357331e9383d@gerdon-MS-7346.mail>
Subject: Confirmation instructions
Mime-Version: 1.0
Content-Type: text/html;
 charset=UTF-8
Content-Transfer-Encoding: 7bit

<p>Welcome ...@gmail.com!</p>

<p>You can confirm your account email through the link below:</p>

<p><a href="http://localhost:3000/users/confirmation?confirmation_token=zYTXtSnJfom1oNS-o8Fy">Confirm my account</a></p>

答案 10 :(得分:0)

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

  

确保输入的小数点不超过一位,并且在小数点右侧输入的位数不超过2位。

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

  

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