代码之家  ›  专栏  ›  技术社区  ›  Andrew Grant

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

  •  50
  • Andrew Grant  · 技术社区  · 17 年前

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

    谢谢

    11 回复  |  直到 14 年前
        1
  •  53
  •   ilent2    14 年前

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

    所以现在你只需要:

    myTextField.keyboardType=UIKeyboardTypeDecimalPad;
    
        2
  •  50
  •   shek    17 年前

    更优雅的解决方案恰好也是最简单的。

    您不需要十进制分隔键

    • 用户输入2:$0.12
    • 用户输入3:$1.23

    请注意,我们是如何根据用户的输入推断十进制分隔符的。现在,如果用户想要输入$1.00,他们只需输入数字1-0-0。

    NSNumberFormatter *currencyFormatter = [[NSNumberFormatter alloc] init];
    [currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
    int currencyScale = [currencyFormatter maximumFractionDigits];
    

    例如,日元的最大小数位数为0。因此,在处理日元输入时,没有小数分隔符,因此甚至不需要担心小数金额。

    这种解决问题的方法使您可以使用苹果提供的库存数字输入键盘,而不必担心定制键盘、正则表达式验证等问题。

        3
  •  12
  •   Mason    14 年前

    下面是一个在公认答案中建议的解决方案示例。这不处理其他货币或任何东西-在我的情况下,我只需要美元的支持,无论语言环境/货币如何,所以这对我来说是可以的:

    -(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)格式字符串舍入我们在退格部分删除的任何精度。

        4
  •  3
  •   Alex    17 年前

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

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

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

        5
  •  2
  •   Martin v. Löwis    17 年前

    根据具体的应用程序,在iphone上提供用户可以选择位置的滑块可能是更好的选择。那么根本不需要输入数字。

        6
  •  2
  •   Jeroen Heijmans    17 年前

        7
  •  2
  •   Richard    15 年前

    我建立了一个自定义数字键盘视图控制器与小数点。。。过来看:

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

        8
  •  1
  •   Screwtape    15 年前

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

        9
  •  1
  •   Daniel Thorpe    14 年前

    下面介绍如何在不使用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 并设置所需的格式/最大分数位数。

        10
  •  0
  •   chasew    10 年前

     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
  •  0
  •   Stunner    9 年前

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

    确保输入的小数点不超过一个,且在所述小数点右侧输入的数字不超过两位。

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

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