尝试格式化UITextField,使其像货币计算器一样,仅用于iOS中的数字输入



我的应用程序中有一个UITextField,它应该只接收来自用户的数字输入。这个数字输入应该表示货币(即只有两个小数点),当没有输入任何内容时,默认值为0.00。我还想有一个"$"符号,它位于最左边,与数字右对齐,这样数字就会从右向左移动,像这样:

。当输入数字"1234.56"时。

1。 .

2。 .

3。 .

4。 .

5。 .

6。 .

7。美元1234 .56点 .

8。

我让UITextField右对齐,这样它已经把数字从右边移到了左边。但是,我需要将"$"放在UITextField中,并且我希望将默认的0.00值修改为用户每次输入一个数字的数字。用户不应该输入小数点,因为它应该已经在文本字段中保存了它的位置。然后我想要的数字有一个","被自动输入以分开每三个数字。我希望应用程序这样做作为用户正在输入的数字,而不是格式化后,当一切都输入。我该怎么做呢?我看到很多人说我要使用NSNumberFormatter,但我想知道我如何将它与UITextField结合使用,以便它在飞行中格式化数字文本,如上所述?

我发现以下问题张贴在StackOverflow前一段时间:

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

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

这是一个很好的方法。记住在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;
}

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
    }

这是我在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
}

您可能需要检查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编程……)。但是我不知道有谁写过这样的控件,并且是开源的。

我从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
}

在具有不同locale的操场中使用该方法得到了这些结果(抱歉,还不能直接嵌入)。

相关内容

最新更新