12

我的UITextField应用程序中有一个应该只接收来自用户的数字输入。这个数字输入应该代表货币(即只有两位小数),当没有输入任何内容时,默认值为0.00 。我还想在最左边有一个“$”符号,数字右对齐,这样数字从右到左移动,如下所示:

例如,当输入数字“1234.56”时。

1. 0.00 美元

2. 0.01 美元

3. 0.12 美元

4. 1.23 美元

5. 12.34 美元

6. 123.45 美元

7. 1,234.56 美元

8.等等……

我将UITextField右对齐,以便它已经将数字从右侧移到左侧。但是,我需要将“$”放在UITextField中,并且我希望将默认的0.00值修改为用户一次输入一位数字的数字。用户不必输入小数点,因为它应该已经在保持其位置的文本字段中。然后,我希望该号码有一个“,”,以便自动输入以分隔每三个数字。我希望应用程序在用户输入数字时执行此操作,并且在输入所有内容后不进行格式化。我该怎么做?我看到很多人说我要使用NSNumberFormatter,但我想知道如何将它与它结合使用UITextField,以便动态格式化数字文本,如上所述?

我前段时间在 StackOverflow 上发现了以下问题:

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

但我想知道如何将它作为我的问题的解决方案。

4

5 回答 5

15

这是一个很好的方法。记得在 viewDidLoad 方法中设置你的 UITextField 为 self 并且你的头文件必须符合 UITextFieldDelegate 协议

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{

    NSString *cleanCentString = [[textField.text componentsSeparatedByCharactersInSet: [[NSCharacterSet decimalDigitCharacterSet] invertedSet]] componentsJoinedByString:@""];
    NSInteger centValue = [cleanCentString intValue];
    NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
    NSNumber *myNumber = [f numberFromString:cleanCentString];
    NSNumber *result;

    if([textField.text length] < 16){
        if (string.length > 0)
        {
            centValue = centValue * 10 + [string intValue];
            double intermediate = [myNumber doubleValue] * 10 +  [[f numberFromString:string] doubleValue];
           result = [[NSNumber alloc] initWithDouble:intermediate];
        }
        else
        {
            centValue = centValue / 10;
            double intermediate = [myNumber doubleValue]/10;
            result = [[NSNumber alloc] initWithDouble:intermediate];
        }

        myNumber = result;
         NSLog(@"%ld ++++ %@", (long)centValue, myNumber);
            NSNumber *formatedValue;
            formatedValue = [[NSNumber alloc] initWithDouble:[myNumber doubleValue]/ 100.0f];
            NSNumberFormatter *_currencyFormatter = [[NSNumberFormatter alloc] init];
            [_currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
            textField.text = [_currencyFormatter stringFromNumber:formatedValue];
            return NO;
    }else{

        NSNumberFormatter *_currencyFormatter = [[NSNumberFormatter alloc] init];
        [_currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
        textField.text = [_currencyFormatter stringFromNumber:00];

        UIAlertView *alert = [[UIAlertView alloc]initWithTitle: @"Deposit Amount Limit"
                                                       message: @"You've exceeded the deposit amount limit. Kindly re-input amount"
                                                      delegate: self
                                             cancelButtonTitle:@"Cancel"
                                             otherButtonTitles:@"OK",nil];

        [alert show];
        return NO;
    }
    return YES;
}
于 2014-06-21T14:48:09.840 回答
7

SWIFT 3 的更新答案

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

        let formatter = NumberFormatter()
        formatter.minimumFractionDigits = 2
        formatter.maximumFractionDigits = 2

        if string.characters.count > 0 {
            amountTypedString += string
            let decNumber = NSDecimalNumber(string: amountTypedString).multiplying(by: 0.01)
            let newString = "$" + formatter.string(from: decNumber)!
            textField.text = newString
        } else {
            amountTypedString = String(amountTypedString.characters.dropLast())
            if amountTypedString.characters.count > 0 {
                let decNumber = NSDecimalNumber(string: amountTypedString).multiplying(by: 0.01)
                let newString = "$" +  formatter.string(from: decNumber)!
                textField.text = newString
            } else {
                textField.text = "$0.00"
            }

        }
        return false

    }

    func textFieldShouldClear(_ textField: UITextField) -> Bool {
        amountTypedString = ""
        return true
    }
于 2017-03-11T09:53:46.343 回答
3

这是我在 Swift 中的解决方案。我的方法是跟踪输入的数字并将其乘以 0.01,并使用 NSNumberFormatter 将结果数字设置为 2 个小数点。请注意,我将文本字段键盘设置为数字键盘。

amountTextfield?.keyboardType = UIKeyboardType.NumberPad

var amountTypedString = ""

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {

    let formatter = NSNumberFormatter()
    formatter.minimumFractionDigits = 2
    formatter.maximumFractionDigits = 2

    if string.characters.count > 0 {
        amountTypedString += string
        let decNumber = NSDecimalNumber(float: Float(amountTypedString)!).decimalNumberByMultiplyingBy(0.01)
        let newString = "$" + formatter.stringFromNumber(decNumber)!
        textfield.text = newString
    } else {
        amountTypedString = String(amountTypedString.characters.dropLast())
        if amountTypedString.characters.count > 0 {
            let decNumber = NSDecimalNumber(float: Float(amountTypedString)!).decimalNumberByMultiplyingBy(0.01)
            let newString = "$" +  formatter.stringFromNumber(decNumber)!
            textfield.text = newString
        } else {
            textfield.text = "$0.00"
        }

    }
    return false

}

func textFieldShouldClear(textField: UITextField) -> Bool {
    amountTypedString = ""
    return true
}
于 2016-04-14T18:24:28.500 回答
1

您可能需要检查UITextFieldDelegate协议。通过将某些东西(通常是您的 ViewController 类)指定为 UITextField 的委托,您将能够从控件接收交互式文本输入事件。尤其:

- (BOOL)textField:(UITextField *)textField 
        shouldChangeCharactersInRange:(NSRange)range 
        replacementString:(NSString *)string

通过从该方法返回 NO,您可以防止文本字段应用用户按下的键。

但是,即使您返回 NO,也没有什么可以阻止您使用传递给委托方法的信息来自己操作代码中的文本字段内容。

以伪代码形式:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    if (string-contains-number) {
        alter textfield.text to be what it should be now, adding the number;
    }
    else {
        string contains something you don't wan the user typing, so ignore it.
    }

    // Tell iOS not to apply the user's change (since you just did by 
    // updating the text yourself:
    return NO;
}

免责声明:我还没有编写实际代码来测试,因此更改此委托方法中的代码可能会导致另一个 shouldChangeCharactersInRange: 消息触发。不过,我不相信情况会如此。我不相信当您更改代码中的文本时会触发委托事件。

这显然不如已经实现了数字文本输入框的所有规则的自定义控件(我现在回想起多年的 Visual Basic 编程......)。但我不知道有人编写和开源的任何此类控制。

于 2013-03-05T07:41:56.770 回答
0

我从 julien 那里得到了答案并对其进行了修改,以便支持具有不同货币格式的其他语言环境。我还存储了数字格式化程序以供​​重复使用,因此不会每次都创建它们,这是一项昂贵的操作。

通过忽略任何会导致存储值溢出的输入来处理溢出。

此解决方案假定仅在文本字段的末尾输入文本,因此无论文本光标在输入之前的位置如何,都只会在末尾操作。

let outputFormatter: NSNumberFormatter = {
    let formatter = NSNumberFormatter()
    formatter.numberStyle = .CurrencyStyle
    if formatter.maximumFractionDigits > 0 {
        formatter.multiplier = pow(10, -CGFloat(formatter.maximumFractionDigits))
    }
    return formatter
}()

let inputFormatter: NSNumberFormatter = {
    let formatter = NSNumberFormatter()
    formatter.numberStyle = .DecimalStyle
    return formatter
}()

private var value: UInt = 0

var currencyValue: NSDecimalNumber {
    let exponent = Int16(truncatingBitPattern: outputFormatter.maximumFractionDigits)
    return NSDecimalNumber(mantissa: UInt64(value), exponent: -exponent, isNegative: false)
}

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    if string.isEmpty {
        /* User pressed backspace, shift right one space. */
        value /= 10
    } else if let number = inputFormatter.numberFromString(string)?.unsignedIntegerValue {
        /* User entered a number, shift left one space and add. */
        let shiftedValue = UInt.multiplyWithOverflow(value, 10)
        let addedValue = UInt.addWithOverflow(shiftedValue.0, number)
        if !shiftedValue.overflow && !addedValue.overflow {
            value = addedValue.0
        }
    }

    textField.text = outputFormatter.stringFromNumber(NSDecimalNumber(unsignedInteger: value))
    return false
}

func textFieldShouldClear(textField: UITextField) -> Bool {
    value = 0
    return true
}

在具有各种语言环境的操场上使用它给了我这些结果 (抱歉,还不能直接嵌入)。

于 2016-04-27T04:10:54.683 回答