it-swarm.dev

Ondalık noktalarla sayısal değerler girmenin en iyi yolu nedir?

Uygulamamda kullanıcıların ondalık basamaklarla sayısal değerler girebilmeleri gerekir. İPhone bu amaç için özel bir klavye sağlamıyor - yalnızca bir rakam tuş takımı ve sayıları ve sembolleri olan bir klavye.

Sonuncusunu düzenlemek ve sayısal olmayan bir girişin nihai sonucu düzenlemek zorunda kalmadan girilmesinin önlenmesinin kolay bir yolu var mı?

Teşekkürler!

50
Andrew Grant

Daha şık bir çözüm de en basit olur.

Ondalık ayırıcı tuşa ihtiyacınız yok

Niye ya? Çünkü bunu sadece kullanıcının girişinden çıkartabilirsiniz. Örneğin, ABD yerel ayarında ne gireceğiniz 1.23 $ iken, 1-2-3 sayılarını girerek başlayabilirsiniz (bu sırayla). Sistemde, her karakter girildiğinde, bu şu şekilde kabul edilir:

  • kullanıcı 1: 0,01 $ girer
  • kullanıcı 2: 0,12 $ girer
  • kullanıcı 3: 1,23 $ girer

Kullanıcının girişine bağlı olarak ondalık ayırıcıyı nasıl çıkardığımıza dikkat edin. Şimdi, kullanıcı 1,00 ABD doları girmek isterse, sadece 1-0-0 sayılarını girer.

Kodunuzun farklı bir yerel ayarın para birimlerini kullanması için, para biriminin maksimum kesir hanesini almanız gerekir. Bu, aşağıdaki kod pasajıyla yapılabilir:

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

Örneğin, Japon yeninde 0'ın maksimum bir kesir basamağı vardır. Dolayısıyla, yen girişi ile çalışırken, ondalık ayırıcı yoktur ve bu nedenle kesirli miktarlar için endişelenmenize gerek yoktur.

Soruna bu yaklaşım, Apple tarafından sağlanan stok sayısal giriş tuş takımını, özel tuş takımları, regex doğrulama vb.

49
shek

Ben iOS 4.1'den itibaren yeni UIKeyboardTypeDecimalPad kullanabileceğinizi belirtmenin iyi olacağını düşünüyorum.

Yani şimdi yapmanız gerekenler:

myTextField.keyboardType=UIKeyboardTypeDecimalPad;
52
Zebs

İşte kabul edilen cevapta önerilen çözüm için bir örnek. Bu, diğer para birimlerini veya hiçbir şeyle ilgilenmez - benim durumumda, yerel ayar/para birimi ne olursa olsun, sadece dolar için desteğe ihtiyacım vardı.

-(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;
}

Mermiler ve döşemeler önemlidir a) kayan nokta gösterimi nedeniyle bazen .00001 kaybedebilir ya da her neyse ve b) geri dönme bölümünde sildiğimiz herhangi bir hassasiyeti tamamlayan biçim dizgisi.

12
Mike Weller

Ben de aynı şeyi yapmak istedim, düz ondalık değerler yerine para birimleri dışında. 

Bir UITextField ve bir UILabel içeren özel bir görünüm oluşturdum. Etiket metin alanını kapsar, ancak metin alanı yine de dokunuş alır. Metin alanındaki değişiklikleri gözlemlemek için UITextFieldTextDidChange bildirimini kullanıyorum (ve sonuçtaki sayıyı biçimlendirilmiş bir para birimi değerine dönüştürmek için bir NSNumberFormatter kullandım) etiketi güncellemek için.

Kullanıcının ekleme noktasını yeniden konumlandırmasına izin veren büyüteç özelliğini devre dışı bırakmak için, özel bir UITextField alt sınıfını kullanmanız ve touchesBegan: withEvent: öğesini geçersiz kılmanız ve hiçbir şey yapmaması için ayarlamanız gerekir.

Çözümüm ihtiyacınız olandan farklı olabilir, çünkü ondalık nokta her zaman sabittir - ondalık basamağın ardından kaç basamak olması gerektiğini belirlemek için sistemin para birimi ayarını kullanırım. Ancak, sayısal tuş takımının üzerinde ondalık bir nokta yoktur. Ve klavyeye herhangi bir düğme ekleyemezsiniz (bu özellikle ağırlaştırıcıdır çünkü klavyenin sol alt köşesinde ondalık bir nokta için mükemmel olan boş bir düğme vardır!) Bu yüzden bunun için bir çözümüm yok. , ne yazık ki.

3
Alex

Bir basamak (Martin v. Löwis tarafından önerildiği şekilde) veya her bir basamak için ayrı bir tekerleği olan bir UIPickerView kullanmak isteyebilirsiniz.

2
Jeroen Heijmans

Ondalık noktaya sahip özel bir Number pad view controller oluşturdum ... kontrol edin:

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

2
Richard

Özel uygulamaya bağlı olarak, kullanıcının bir konum seçebileceği bir kaydırıcı sağlamak iphone'da daha iyi bir seçim olabilir. O zaman hiçbir rakam girmeniz gerekmez.

2

İşte float, round () veya ce (() para birimini agnostik şekilde kullanmadan nasıl yapılacağını.

Denetleyiciyi görüntülediğinizde, aşağıdaki örnek değişkenleri ayarlayın (çantanız buysa ilişkili @property deyimleriyle):

@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

ve viewDidLoad yönteminiz aşağıdakileri içermelidir:

- (void)viewDidLoad {
    [super viewDidLoad];

    NSNumberFormatter *aFormatter = [[NSNumberFormatter alloc] init];
    [aFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
    currencyScale = -1 * [aFormatter maximumFractionDigits];
    self.formatter = aFormatter;
    [aFormatter release];
}

Ardından UITextFieldDelegate yöntemlerinizi aşağıdaki şekilde uygulayın:

#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;  
}

Bunu sadece pound ve pence ile test ettim, ancak Japon Yeni ile de çalışması gerekiyor. Ondalık para birimlerini olmayan amaçlar için biçimlendirmek istiyorsanız, sadece NSNumberFormatter ile ilgili belgeleri okuyun ve istediğiniz biçimde/maximumFractionDigits biçimini ayarlayın.

1
Daniel Thorpe

İOS4.1'den itibaren yeni bir klavye türü olan UIKeyboardTypeNumberPad var, ancak ne yazık ki, henüz olduğu gibi, Arayüz Oluşturucu seçim listesinde görünmüyor.

1
Screwtape

STATextField uygulamasını kullanabilirsiniz ve currencyRepresentation'ı YES'e ayarlayın:

Birden fazla ondalık nokta girilmemesini ve belirtilen ondalık basamağın sağına 2 rakamdan fazla girilmemesini sağlar.

Ayrıca var olan STAATMTextField para birimi modunu destekleyen ve ATM metin girişini varsayılan olarak:

ATM makinesi giriş davranışını taklit eden bir metin alanı sağlar.

0
Stunner

Mike Weller'in gönderisinin Swift 2 uygulaması, aynı zamanda sadece 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
ccwasden