EditText'te numberDecimal inputType ile ondalık ayırıcı virgül (',')


133

inputType numberDecimalİçinde EditTextnokta kullanır. '' ondalık ayırıcı olarak. Avrupa'da bunun yerine virgül kullanmak yaygındır. Yerel ayarım Almanca olarak ayarlanmış olsa da, ondalık ayırıcı hala '.'

Ondalık ayırıcı olarak virgül almanın bir yolu var mı?



1
bu hata nihayet Android O'da düzeltildi: issuetracker.google.com/issues/36907764
Lovis

düzeltildiğini söylüyorlar ancak düzeltildiğini onaylayamıyorum? yapabilir misin?
sebastian

5
En azından Android 8.1 (diğer adıyla LineageOS 15.1) çalıştıran Nexus 4 cihazımda düzeltilmediğini onaylayabilirim. Ayarlar-> Dil Fransızca (Fransa) olarak ayarlandığında, android: inputType = "numberDecimal" içeren bir EditText, ',' (virgül) ayırıcısını sunar, ancak yine de virgülü kabul etmeyi reddeder. Teklif edilen '.' (ondalık nokta) kabul edilir. Bu hatanın ilk bildirilmesinden bu yana 9 yıldan fazla zaman geçti. Bu bir çeşit rekor mu? Topal.
pete

Yanıtlar:


105

Bir çözüm (Google bu hatayı düzeltene kadar) bir ve EditTextile kullanmaktır .android:inputType="numberDecimal"android:digits="0123456789.,"

Sonra EditText'e aşağıdaki afterTextChanged ile bir TextChangedListener ekleyin:

public void afterTextChanged(Editable s) {
    double doubleValue = 0;
    if (s != null) {
        try {
            doubleValue = Double.parseDouble(s.toString().replace(',', '.'));
        } catch (NumberFormatException e) {
            //Error
        }
    }
    //Do something with doubleValue
}

1
Klavyenizde virgülün (,) gösterilmesi için @Zoombie, cihazınızda ayarlanan dile bağlıdır. Girişinizin türü numberDecimal ise ve diliniz İngilizce (ABD) ise, Nexus cihazlarda gösterilecektir (referans). Nexus olmayan cihazların buna saygı göstermemesi mümkündür
hcpl

11
Çalışır, ancak "24,22.55" gibi bir metnin geçmesine izin verdiğini unutmayın. Bunu düzeltmek için ek doğrulama eklemeniz gerekebilir!
dimsuz

8
Hala gidilecek yol bu mu?
Willi Mentzel

Daha da iyisi, char localizedSeparator = DecimalFormatSymbols.getInstance () kullanın. GetDecimalSeparator (); localizedFloatString = localizedFloatString.replace ('.', localizedSeparator);
southerton

4
Görünüşe göre bu sadece bir hatayı diğeriyle takas ediyor. Yukarıda uygulandığı gibi, bu, yerine kullanan yerel ayarlar için çalışacaktır. dünya çapında daha yaygın olan tersi pahasına. @ southerton'ın ince ayarı bu konuda yardımcı olur, ancak kullanıcılarınız bir. ve girişte bir, görünür.
Nick

30

Burada sunulan 'basamaklı' çözümlerin bir varyasyonu:

char separator = DecimalFormatSymbols.getInstance().getDecimalSeparator();
input.setKeyListener(DigitsKeyListener.getInstance("0123456789" + separator));

Yerel ayırıcı dikkate alınarak.


Bu, orijinal soruya verilebilecek en temiz cevaptır. Teşekkürler
peter.bartos

Bunu onCreate () içine yerleştirin, gidilecek yol budur, IMHO.
TechNyquist

6
Bunu beğendim, ancak dikkatli olun ... kullanıcının yerel ayarını önemsemeyen klavyeler var, bu yüzden kullanıcı ,klavyelerinde anahtarı olmayan kullanıcılar . Örnekler: Samsung klavye (KitKat).
Brais Gabin

2
Bu, yinelenen ondalık ayırıcılara izin verecektir.
İşlemek

19

EditText için Kod Para Birimi Maskesinin Ardından (123.125.155 $)

Xml Düzeni

  <EditText
    android:inputType="numberDecimal"
    android:layout_height="wrap_content"
    android:layout_width="200dp"
    android:digits="0123456789.,$" />

kod

EditText testFilter=...
testFilter.addTextChangedListener( new TextWatcher() {
        boolean isEdiging;
        @Override public void onTextChanged(CharSequence s, int start, int before, int count) { }
        @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { }

        @Override public void afterTextChanged(Editable s) {
            if(isEdiging) return;
            isEdiging = true;

            String str = s.toString().replaceAll( "[^\\d]", "" );
            double s1 = Double.parseDouble(str);

            NumberFormat nf2 = NumberFormat.getInstance(Locale.ENGLISH);
            ((DecimalFormat)nf2).applyPattern("$ ###,###.###");
            s.replace(0, s.length(), nf2.format(s1));

            isEdiging = false;
        }
    });

16

Bu, Android SDK'da bilinen bir hatadır . Tek çözüm kendi yazılım klavyenizi oluşturmaktır. Burada bir uygulama örneği bulabilirsiniz .


15
Dört yıl sonra herhangi bir haber var mı?
Antonio Sesto

Bunu Xamarin.Forms'da da deneyimlemek. Kültür {se-SV} ve sayısal tuş takımı bot "," (ondalık ayırıcı) ve "." (bin grup ayırıcı) ancak "," tuşuna basıldığında metin alanına hiçbir şey girilmez ve hiçbir olay ortaya
çıkmaz

Hatanın hala var olduğunu doğrulayabilirim.
Lensflare

Android O geliştirici önizlemesinde düzeltildi
R00We

6

EditText'i programlı olarak başlatıyorsanız, Martins cevabı çalışmayacaktır. Devam ettim ve dahil edileni değiştirdimDigitsKeyListener ondalık ayırıcı olarak hem virgül hem de döneme izin vermek için API 14'ten sınıfı .

Bunu kullanmak setKeyListener()için EditText, örn.

// Don't allow for signed input (minus), but allow for decimal points
editText.setKeyListener( new MyDigitsKeyListener( false, true ) );

Ancak, TextChangedListenervirgül yerine nokta koyduğunuzda Martin'in hilesini yine de kullanmanız gerekir.

import android.text.InputType;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.method.NumberKeyListener;
import android.view.KeyEvent;

class MyDigitsKeyListener extends NumberKeyListener {

    /**
     * The characters that are used.
     *
     * @see KeyEvent#getMatch
     * @see #getAcceptedChars
     */
    private static final char[][] CHARACTERS = new char[][] {
        new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' },
        new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-' },
        new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', ',' },
        new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '.', ',' },
    };

    private char[] mAccepted;
    private boolean mSign;
    private boolean mDecimal;

    private static final int SIGN = 1;
    private static final int DECIMAL = 2;

    private static MyDigitsKeyListener[] sInstance = new MyDigitsKeyListener[4];

    @Override
    protected char[] getAcceptedChars() {
        return mAccepted;
    }

    /**
     * Allocates a DigitsKeyListener that accepts the digits 0 through 9.
     */
    public MyDigitsKeyListener() {
        this(false, false);
    }

    /**
     * Allocates a DigitsKeyListener that accepts the digits 0 through 9,
     * plus the minus sign (only at the beginning) and/or decimal point
     * (only one per field) if specified.
     */
    public MyDigitsKeyListener(boolean sign, boolean decimal) {
        mSign = sign;
        mDecimal = decimal;

        int kind = (sign ? SIGN : 0) | (decimal ? DECIMAL : 0);
        mAccepted = CHARACTERS[kind];
    }

    /**
     * Returns a DigitsKeyListener that accepts the digits 0 through 9.
     */
    public static MyDigitsKeyListener getInstance() {
        return getInstance(false, false);
    }

    /**
     * Returns a DigitsKeyListener that accepts the digits 0 through 9,
     * plus the minus sign (only at the beginning) and/or decimal point
     * (only one per field) if specified.
     */
    public static MyDigitsKeyListener getInstance(boolean sign, boolean decimal) {
        int kind = (sign ? SIGN : 0) | (decimal ? DECIMAL : 0);

        if (sInstance[kind] != null)
            return sInstance[kind];

        sInstance[kind] = new MyDigitsKeyListener(sign, decimal);
        return sInstance[kind];
    }

    /**
     * Returns a DigitsKeyListener that accepts only the characters
     * that appear in the specified String.  Note that not all characters
     * may be available on every keyboard.
     */
    public static MyDigitsKeyListener getInstance(String accepted) {
        // TODO: do we need a cache of these to avoid allocating?

        MyDigitsKeyListener dim = new MyDigitsKeyListener();

        dim.mAccepted = new char[accepted.length()];
        accepted.getChars(0, accepted.length(), dim.mAccepted, 0);

        return dim;
    }

    public int getInputType() {
        int contentType = InputType.TYPE_CLASS_NUMBER;
        if (mSign) {
            contentType |= InputType.TYPE_NUMBER_FLAG_SIGNED;
        }
        if (mDecimal) {
            contentType |= InputType.TYPE_NUMBER_FLAG_DECIMAL;
        }
        return contentType;
    }

    @Override
    public CharSequence filter(CharSequence source, int start, int end,
                               Spanned dest, int dstart, int dend) {
        CharSequence out = super.filter(source, start, end, dest, dstart, dend);

        if (mSign == false && mDecimal == false) {
            return out;
        }

        if (out != null) {
            source = out;
            start = 0;
            end = out.length();
        }

        int sign = -1;
        int decimal = -1;
        int dlen = dest.length();

        /*
         * Find out if the existing text has '-' or '.' characters.
         */

        for (int i = 0; i < dstart; i++) {
            char c = dest.charAt(i);

            if (c == '-') {
                sign = i;
            } else if (c == '.' || c == ',') {
                decimal = i;
            }
        }
        for (int i = dend; i < dlen; i++) {
            char c = dest.charAt(i);

            if (c == '-') {
                return "";    // Nothing can be inserted in front of a '-'.
            } else if (c == '.' ||  c == ',') {
                decimal = i;
            }
        }

        /*
         * If it does, we must strip them out from the source.
         * In addition, '-' must be the very first character,
         * and nothing can be inserted before an existing '-'.
         * Go in reverse order so the offsets are stable.
         */

        SpannableStringBuilder stripped = null;

        for (int i = end - 1; i >= start; i--) {
            char c = source.charAt(i);
            boolean strip = false;

            if (c == '-') {
                if (i != start || dstart != 0) {
                    strip = true;
                } else if (sign >= 0) {
                    strip = true;
                } else {
                    sign = i;
                }
            } else if (c == '.' || c == ',') {
                if (decimal >= 0) {
                    strip = true;
                } else {
                    decimal = i;
                }
            }

            if (strip) {
                if (end == start + 1) {
                    return "";  // Only one character, and it was stripped.
                }

                if (stripped == null) {
                    stripped = new SpannableStringBuilder(source, start, end);
                }

                stripped.delete(i - start, i + 1 - start);
            }
        }

        if (stripped != null) {
            return stripped;
        } else if (out != null) {
            return out;
        } else {
            return null;
        }
    }
}

doc'tan: KeyListener yalnızca bir uygulamanın kendi ekran üstü tuş takımına sahip olduğu ve aynı zamanda onunla eşleşecek şekilde sabit klavye olaylarını işlemek istediği durumlarda kullanılmalıdır. developer.android.com/reference/android/text/method/…
Loda

6

aşağıdakileri farklı yerel ayarlar için kullanabilirsiniz

private void localeDecimalInput(final EditText editText){

    DecimalFormat decFormat = (DecimalFormat) DecimalFormat.getInstance(Locale.getDefault());
    DecimalFormatSymbols symbols=decFormat.getDecimalFormatSymbols();
    final String defaultSeperator=Character.toString(symbols.getDecimalSeparator());

    editText.addTextChangedListener(new TextWatcher() {

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {

        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {

        }

        @Override
        public void afterTextChanged(Editable editable) {
            if(editable.toString().contains(defaultSeperator))
                editText.setKeyListener(DigitsKeyListener.getInstance("0123456789"));
            else
                editText.setKeyListener(DigitsKeyListener.getInstance("0123456789" + defaultSeperator));
        }
    });
}

Bu benim için en iyi çözüm, ancak klavyede "," koma göstermeyen Samsung gibi bazı telefonlarda sorunlar var. Bu yüzden bunu hem virgül hem de
noktaya

5

Geçerli bir giriş olarak virgül eklemek için aşağıdaki geçici çözümü de kullanabilirsiniz: -

XML aracılığıyla:

<EditText
    android:inputType="number"
    android:digits="0123456789.," />

Programlı:

EditText input = new EditText(THE_CONTEXT);
input.setKeyListener(DigitsKeyListener.getInstance("0123456789.,"));

Bu şekilde Android sistemi sayıların klavyesini gösterecek ve virgül girişine izin verecektir. Umarım bu soruya cevap verir :)


Bu çözümle "," öğesine dokunduğunuzda, ancak düzenleme metni "" gösterilir.
Mara Jimenez

2

Mono (Droid) çözümleri için:

decimal decimalValue = decimal.Parse(input.Text.Replace(",", ".") , CultureInfo.InvariantCulture);

1

Şunları yapabilirsiniz:

DecimalFormatSymbols d = DecimalFormatSymbols.getInstance(Locale.getDefault());
input.setFilters(new InputFilter[] { new DecimalDigitsInputFilter(5, 2) });
input.setKeyListener(DigitsKeyListener.getInstance("0123456789" + d.getDecimalSeparator()));

Ve sonra bir giriş filtresi kullanabilirsiniz:

    public class DecimalDigitsInputFilter implements InputFilter {

Pattern mPattern;

public DecimalDigitsInputFilter(int digitsBeforeZero, int digitsAfterZero) {
    DecimalFormatSymbols d = new DecimalFormatSymbols(Locale.getDefault());
    String s = "\\" + d.getDecimalSeparator();
    mPattern = Pattern.compile("[0-9]{0," + (digitsBeforeZero - 1) + "}+((" + s + "[0-9]{0," + (digitsAfterZero - 1) + "})?)||(" + s + ")?");
}

@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {

    Matcher matcher = mPattern.matcher(dest);
    if (!matcher.matches())
        return "";
    return null;
}

}


bin ile yüz arasında bir boşluk olabilir, bu kalıp biçimlendirilmiş girişi reddeder
Eric Zhao

1

IMHO bu problem için en iyi yaklaşım sadece InputFilter kullanmaktır. Güzel bir özet burada DecimalDigitsInputFilter . O zaman şunları yapabilirsiniz:

editText.setInputType(TYPE_NUMBER_FLAG_DECIMAL | TYPE_NUMBER_FLAG_SIGNED | TYPE_CLASS_NUMBER)
editText.setKeyListener(DigitsKeyListener.getInstance("0123456789,.-"))
editText.setFilters(new InputFilter[] {new DecimalDigitsInputFilter(5,2)});

Büyüleyici çalıştı, teşekkürler! (yukarıdaki pek çok yanlış çözümden sonra ... :() Ama bir sorum var: Ekranda nokta (".") değil görüntülenen virgül (",") öğesini nasıl elde edebilirim çünkü Macaristan'da ondalık ayırıcı olarak virgül kullanıyoruz .
Abigail La'Fay

1
android: digits = "0123456789," ayarı EditText'e eklenebilir. Dahası, DecimalDigitsInputFilter'da null döndürmek yerine, stackoverflow.com/a/40020731/1510222 yanıtına göre source.replace (".", ",") Döndürebilirsiniz, standart bir klavyede noktayı gizlemenin bir yolu yoktur
Arkadiusz Cieśliński

1

girdi kullanımınızı yerelleştirmek için:

char sep = DecimalFormatSymbols.getInstance().getDecimalSeparator();

ve sonra ekleyin:

textEdit.setKeyListener(DigitsKeyListener.getInstance("0123456789" + sep));

"," ile "" değiştirmeyi unutmayın. böylece Float veya Double, hatasız olarak ayrıştırabilir.


1
Bu çözüm birden çok virgül girmeye izin verir
Leo Droidcoder

1

Buradaki diğer tüm yayınlarda büyük boşluklar vardı, bu yüzden işte bir çözüm:

  • Bölgeye göre virgül veya nokta uygulayın, zıtını yazmanıza izin vermez.
  • EditText bir değerle başlıyorsa, gerektiği gibi doğru ayırıcıyı değiştirir.

XML'de:

<EditText
    ...
    android:inputType="numberDecimal" 
    ... />

Sınıf değişkeni:

private boolean isDecimalSeparatorComma = false;

OnCreate'de, geçerli yerel ayarda kullanılan ayırıcıyı bulun:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    NumberFormat nf = NumberFormat.getInstance();
    if (nf instanceof DecimalFormat) {
        DecimalFormatSymbols sym = ((DecimalFormat) nf).getDecimalFormatSymbols();
        char decSeparator = sym.getDecimalSeparator();
        isDecimalSeparatorComma = Character.toString(decSeparator).equals(",");
    }
}

Ayrıca onCreate, geçerli bir değer yüklüyorsanız güncellemek için bunu kullanın:

// Replace editText with commas or periods as needed for viewing
String editTextValue = getEditTextValue(); // load your current value
if (editTextValue.contains(".") && isDecimalSeparatorComma) {
    editTextValue = editTextValue.replaceAll("\\.",",");
} else if (editTextValue.contains(",") && !isDecimalSeparatorComma) {
    editTextValue = editTextValue.replaceAll(",",".");
}
setEditTextValue(editTextValue); // override your current value

Ayrıca onCreate, Dinleyicileri Ekleyin

editText.addTextChangedListener(editTextWatcher);

if (isDecimalSeparatorComma) {
    editText.setKeyListener(DigitsKeyListener.getInstance("0123456789,"));
} else {
    editText.setKeyListener(DigitsKeyListener.getInstance("0123456789."));
}

editTextWatcher

TextWatcher editTextWatcher = new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) { }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) { }

    @Override
    public void afterTextChanged(Editable s) {
        String editTextValue = s.toString();

        // Count up the number of commas and periods
        Pattern pattern = Pattern.compile("[,.]");
        Matcher matcher = pattern.matcher(editTextValue);
        int count = 0;
        while (matcher.find()) {
            count++;
        }

        // Don't let it put more than one comma or period
        if (count > 1) {
            s.delete(s.length()-1, s.length());
        } else {
            // If there is a comma or period at the end the value hasn't changed so don't update
            if (!editTextValue.endsWith(",") && !editTextValue.endsWith(".")) {
                doSomething()
            }
        }
    }
};

doSomething () örneği, veri işleme için standart döneme dönüştür

private void doSomething() {
    try {
        String editTextStr = editText.getText().toString();
        if (isDecimalSeparatorComma) {
            editTextStr = editTextStr.replaceAll(",",".");
        }
        float editTextFloatValue = editTextStr.isEmpty() ?
                0.0f :
                Float.valueOf(editTextStr);

        ... use editTextFloatValue
    } catch (NumberFormatException e) {
        Log.e(TAG, "Error converting String to Double");
    }
}

0

Android'de yerleşik bir sayı biçimlendiricisi vardır.

EditTextOndalık sayılara ve virgüllere izin vermek için bunu ekleyebilirsiniz : android:inputType="numberDecimal"veandroid:digits="0123456789.,"

Daha sonra, kullanıcı kaydet'i tıkladığında veya metin girildikten sonra (bir dinleyici kullanın) kodunuzun herhangi bir yerinde.

// Format the number to the appropriate double
try { 
    Number formatted = NumberFormat.getInstance().parse(editText.getText().toString());
    cost = formatted.doubleValue();
} catch (ParseException e) {
    System.out.println("Error parsing cost string " + editText.getText().toString());
    cost = 0.0;
}

0

Virgülü nokta olarak değiştirmeye sadece düzenleme sırasında karar verdim. İşte benim zor ve göreceli basit çözümüm:

    editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            EditText editText = (EditText) v; 
            String text = editText.getText().toString();
            if (hasFocus) {
                editText.setText(text.replace(",", "."));
            } else {
                if (!text.isEmpty()) {
                    Double doubleValue = Double.valueOf(text.replace(",", "."));
                    editText.setText(someDecimalFormatter.format(doubleValue));
                }
            }
        }
    });

someDecimalFormatter virgül veya nokta kullanır, Yerel Ayara bağlıdır


0

Cevaplarınızın neden bu kadar karmaşık olduğunu bilmiyorum. SDK'da bir hata varsa, onu geçersiz kılmalı veya etrafından dolaşmalısınız.

Bu sorunu çözmek için ikinci yolu seçtim. Dizenizi olarak biçimlendirir Locale.ENGLISHve sonra EditText(boş bir dize olarak bile) dizesine koyarsanız . Misal:

String.format(Locale.ENGLISH,"%.6f", yourFloatNumber);

Bu çözümün peşinden koşarken, sonucunuz gösterilen klavye ile uyumludur. Daha sonra float ve double sayılar, virgül yerine nokta ile programlama dilleri için tipik olarak çalışır.


0

Benim çözümüm:

  • Ana faaliyette:

    char separator =DecimalFormatSymbols.getInstance().getDecimalSeparator(); textViewPitchDeadZone.setKeyListener(DigitsKeyListener.getInstance("0123456789" + separator));

  • Xml dosyasında: android:imeOptions="flagNoFullscreen" android:inputType="numberDecimal"

ve editText'teki double'ı String olarak aldım.


0

Önerilen düzeltmelerin Samsung IME'lerde (en azından S6 ve S9'da) ve belki LG'de çalışmadığını onaylayabilirim. Yerel ayara bakılmaksızın ondalık ayırıcı olarak yine de bir nokta gösterirler. Google'ın IME'sine geçmek bunu düzeltir, ancak çoğu geliştirici için pek bir seçenek değildir.

Ayrıca, Samsung ve / veya LG'nin yapması ve daha sonra eski telefonlarına bile itmesi gereken bir düzeltme olduğundan, bu klavyeler için Oreo'da da düzeltilmedi.

Bunun yerine sayı klavyesi projesini çatalladım ve bir IME: çatal gibi davrandığı bir mod ekledim . Ayrıntılar için proje örneğine bakın. Bu benim için oldukça iyi çalıştı ve bankacılık uygulamalarında gördüğünüz "PIN girişi" sahte IME'lerinin çoğuna benziyor.

Örnek uygulama ekran görüntüsü


0

Aradan 8 yıldan fazla zaman geçti ve şaşırdım, bu sorun henüz çözülmedi ... @Martin tarafından en çok verilen yanıt birden çok ayırıcı yazılmasına izin
verdiği için bu basit sorunla uğraştım, yani kullanıcı "12 ,,, ,,, 12,1,, 21,2, "
Ayrıca ikinci endişe, bazı cihazlarda virgülle sayısal klavyede gösterilmemesidir (veya bir nokta düğmesine birden çok basılması gerekir)

İşte bahsedilen sorunları çözen ve kullanıcının 'yazmasına izin veren geçici çözümüm.' ve ',', ancak EditText'te mevcut yerel ayara karşılık gelen tek ondalık ayırıcıyı görecektir:

editText.apply { addTextChangedListener(DoubleTextChangedListener(this)) }

Ve metin gözlemcisi:

  open class DoubleTextChangedListener(private val et: EditText) : TextWatcher {

    init {
        et.inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_DECIMAL
        et.keyListener = DigitsKeyListener.getInstance("0123456789.,")
    }

    private val separator = DecimalFormatSymbols.getInstance().decimalSeparator

    override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
        //empty
    }

    @CallSuper
    override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
        et.run {
            removeTextChangedListener(this@DoubleTextChangedListener)
            val formatted = toLocalizedDecimal(s.toString(), separator)
            setText(formatted)
            setSelection(formatted.length)
            addTextChangedListener(this@DoubleTextChangedListener)
        }
    }

    override fun afterTextChanged(s: Editable?) {
        // empty
    }

    /**
     * Formats input to a decimal. Leaves the only separator (or none), which matches [separator].
     * Examples:
     * 1. [s]="12.12", [separator]=',' -> result= "12,12"
     * 2. [s]="12.12", [separator]='.' -> result= "12.12"
     * 4. [s]="12,12", [separator]='.' -> result= "12.12"
     * 5. [s]="12,12,,..,,,,,34..,", [separator]=',' -> result= "12,1234"
     * 6. [s]="12.12,,..,,,,,34..,", [separator]='.' -> result= "12.1234"
     * 7. [s]="5" -> result= "5"
     */
    private fun toLocalizedDecimal(s: String, separator: Char): String {
        val cleared = s.replace(",", ".")
        val splitted = cleared.split('.').filter { it.isNotBlank() }
        return when (splitted.size) {
            0 -> s
            1 -> cleared.replace('.', separator).replaceAfter(separator, "")
            2 -> splitted.joinToString(separator.toString())
            else -> splitted[0]
                    .plus(separator)
                    .plus(splitted.subList(1, splitted.size - 1).joinToString(""))
        }
    }
}

0

Basit çözüm, özel bir kontrol yapın. (bu, Xamarin android'de yapılmıştır, ancak java'ya kolayca bağlanmalıdır)

public class EditTextDecimalNumber:EditText
{
    readonly string _numberFormatDecimalSeparator;

    public EditTextDecimalNumber(Context context, IAttributeSet attrs) : base(context, attrs)
    {
        InputType = InputTypes.NumberFlagDecimal;
        TextChanged += EditTextDecimalNumber_TextChanged;
        _numberFormatDecimalSeparator = System.Threading.Thread.CurrentThread.CurrentUICulture.NumberFormat.NumberDecimalSeparator;

        KeyListener = DigitsKeyListener.GetInstance($"0123456789{_numberFormatDecimalSeparator}");
    }

    private void EditTextDecimalNumber_TextChanged(object sender, TextChangedEventArgs e)
    {
        int noOfOccurence = this.Text.Count(x => x.ToString() == _numberFormatDecimalSeparator);
        if (noOfOccurence >=2)
        {
            int lastIndexOf = this.Text.LastIndexOf(_numberFormatDecimalSeparator,StringComparison.CurrentCulture);
            if (lastIndexOf!=-1)
            {
                this.Text = this.Text.Substring(0, lastIndexOf);
                this.SetSelection(this.Text.Length);
            }

        }
    }
}

0

Kullanabilirsiniz inputType="phone", ancak bu durumda çoklu ,veya .mevcut olmakla uğraşmanız gerekir, bu nedenle ek doğrulama gerekli olacaktır.


-1

Bu çözümün burada yazılan diğer çözümlerden daha az karmaşık olduğunu düşünüyorum:

<EditText
    android:inputType="numberDecimal"
    android:digits="0123456789," />

Bu şekilde "." yumuşak klavyede hiçbir şey olmuyor; yalnızca sayılara ve virgüllere izin verilir.


4
bunu yaparsanız, o zaman '.' kullanan tüm yerel ayarları kırarsınız. yerine.
Nick
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.