मुद्रा इनपुट को संपादित करने के लिए बेहतर तरीका editText?


91

मेरे पास एक EditText है, जिसका मूल्य $ 0.00 है। जब आप 1 दबाते हैं, तो यह $ 0.01 में बदल जाता है। प्रेस 4, यह $ 0.14 को जाता है। प्रेस 8, $ 1.48। प्रेस बैकस्पेस, $ 0.14, आदि।

यह काम करता है, समस्या यह है कि अगर कोई मैन्युअल रूप से कर्सर रखता है, तो स्वरूपण में समस्याएं आती हैं। यदि वे दशमलव को हटाना चाहते हैं, तो यह वापस नहीं आएगा। यदि वे कर्सर को दशमलव के सामने रखते हैं और 2 टाइप करते हैं, तो यह $ 2.00 के बजाय $ 02.00 प्रदर्शित करेगा। यदि वे $ को हटाने का प्रयास करते हैं तो यह उदाहरण के बजाय एक अंक को हटा देगा।

यहां वह कोड है जिसका मैं उपयोग कर रहा हूं, मैं किसी भी सुझाव की सराहना करूंगा।

mEditPrice.setRawInputType(Configuration.KEYBOARD_12KEY);
    public void priceClick(View view) {
    mEditPrice.addTextChangedListener(new TextWatcher(){
        DecimalFormat dec = new DecimalFormat("0.00");
        @Override
        public void afterTextChanged(Editable arg0) {
        }
        @Override
        public void beforeTextChanged(CharSequence s, int start,
                int count, int after) {
        }
        @Override
        public void onTextChanged(CharSequence s, int start,
                int before, int count) {
            if(!s.toString().matches("^\\$(\\d{1,3}(\\,\\d{3})*|(\\d+))(\\.\\d{2})?$"))
            {
                String userInput= ""+s.toString().replaceAll("[^\\d]", "");
                if (userInput.length() > 0) {
                    Float in=Float.parseFloat(userInput);
                    float percen = in/100;
                    mEditPrice.setText("$"+dec.format(percen));
                    mEditPrice.setSelection(mEditPrice.getText().length());
                }
            }
        }
    });

1
मेरे अज्ञानता का बहाना है, लेकिन क्या यह कोड जीवन गतिविधि के तरीकों में से एक से स्निपेट है, या वे एक कस्टम वर्ग में बने हैं? क्या आप कृपया अधिक पूर्ण कोड नमूना प्रदान कर सकते हैं? धन्यवाद!
— अर्गुस

मेरे लिए यह काम करता है मैंने इस बाहरी
— कामेच्छा

जवाबों:


153

मैंने आपकी विधि का परीक्षण किया, लेकिन जब मैं बड़ी संख्या का उपयोग करता हूं तो यह विफल हो जाता है ... मैंने इसे बनाया:

private String current = "";
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
    if(!s.toString().equals(current)){
       [your_edittext].removeTextChangedListener(this);

       String cleanString = s.toString().replaceAll("[$,.]", "");
                
       double parsed = Double.parseDouble(cleanString);
       String formatted = NumberFormat.getCurrencyInstance().format((parsed/100));
                    
       current = formatted;
       [your_edittext].setText(formatted);
       [your_edittext].setSelection(formatted.length());
       
       [your_edittext].addTextChangedListener(this);
    }
}

कोटलिन प्रकार:

private var current: String = ""

         override fun onTextChanged(
            s: CharSequence,
            start: Int,
            before: Int,
            count: Int
        ) {
            if (s.toString() != current) {
                discount_amount_edit_text.removeTextChangedListener(this)

                val cleanString: String = s.replace("""[$,.]""".toRegex(), "")

                val parsed = cleanString.toDouble()
                val formatted = NumberFormat.getCurrencyInstance().format((parsed / 100))

                current = formatted
                discount_amount_edit_text.setText(formatted)
                discount_amount_edit_text.setSelection(formatted.length)

                discount_amount_edit_text.addTextChangedListener(this)
            }
        }

36
बेहतर हो सकता है निम्नलिखित के बजाय डॉलर प्रतीक मान करना है: String replaceable = String.format("[%s,.]", NumberFormat.getCurrencyInstance().getCurrency().getSymbol()); String cleanString = s.toString().replaceAll(replaceable, "");
— craigp

6
हम्म, वास्तव में अब यह खुद की कोशिश की है, String replaceable = String.format("[%s,.\\s]", NumberFormat.getCurrencyInstance().getCurrency().getSymbol());
— रीप्लेक्स

6
क्या यह अनुशंसित नहीं है कि परिवर्तन के बाद परिवर्तन नहीं किया onTextChanged() and rather to do so in जाए () `
— कोडिंग्यूसर

3
मुझे यह जानने में दिलचस्पी है कि पाठ बदले गए श्रोता को क्यों हटाया गया और फिर हर बार फिर से जोड़ा गया? मेरे लिए यह काम करता है अगर केवल एक बार जोड़ा जाता है (और मैंने बदलाव के बाद इसे बदल दिया)
— डैनियल विल्सन

5
जब आप 1,00 पाने के लिए 1 -> 0 -> 0 डालते हैं तो मैं काम नहीं करता। इसका कारण यह है कि आप उस बिंदु पर पहुंच जाते हैं जिसमें 0,1 को 010 स्ट्रिंग में और 010 को double10. में बदल दिया जाता है। 10 / 100 = 0,1आप इसे अतीत में नहीं ला सकते।
— जैकब डब्ल्यूडब्ल्यू

30

उपरोक्त कुछ उत्तरों के आधार पर मैंने एक MoneyTextWatcher बनाया जिसे आप निम्नानुसार उपयोग करेंगे:

priceEditText.addTextChangedListener(new MoneyTextWatcher(priceEditText));

और यहाँ वर्ग है:

public class MoneyTextWatcher implements TextWatcher {
    private final WeakReference<EditText> editTextWeakReference;

    public MoneyTextWatcher(EditText editText) {
        editTextWeakReference = new WeakReference<EditText>(editText);
    }

    @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) {
        EditText editText = editTextWeakReference.get();
        if (editText == null) return;
        String s = editable.toString();
        if (s.isEmpty()) return;
        editText.removeTextChangedListener(this);
        String cleanString = s.replaceAll("[$,.]", "");
        BigDecimal parsed = new BigDecimal(cleanString).setScale(2, BigDecimal.ROUND_FLOOR).divide(new BigDecimal(100), BigDecimal.ROUND_FLOOR);
        String formatted = NumberFormat.getCurrencyInstance().format(parsed);
        editText.setText(formatted);
        editText.setSelection(formatted.length());
        editText.addTextChangedListener(this);
    }
}

मैं कुछ समय से इसका उपयोग कर रहा हूं, लेकिन हाल ही में एक छोटी सी समस्या मिली है, यदि आप कुछ कीबोर्ड पर डिलीट बटन दबाते हैं तो यह टेक्स्ट और कारणों के पूरे शब्द / समूह को हटा देता हैjava.lang.NumberFormatException: Bad offset/length
— BluGeni

1
यह पूरी तरह से मेरे लिए काम किया! 'EditText.setSelection (स्वरूपित .length ()) पर ध्यान दें;' प्रश्न में EditText की संपत्ति 'maxLength' उदाहरण के लिए देखा जाना चाहिए। अधिकतम गति == 13; स्वरूपित.लगाव () == 14; यदि 'formatted.length' 'maxLength' से अधिक है निम्न त्रुटि होती है: IndexOutOfBoundsException: setSpan (14 ... 14) समाप्त हो जाती है लंबाई से परे 13 टी.के.एस
— GFPF

1
@BluGeni को ठीक करने के लिए कि केवल टेक्स्ट s श्रोता को हटाने से पहले s.isEmpty चेक जोड़ें अगर (s.isEmpty ()) वापसी; editText.removeTextChangedListener (this); क्लीनस्ट्रिंग लाइन में भी, s.toString () निरर्थक है
— माइक

1
केवल एक सुझाव से बेहतर उत्तर है। .replaceAll ("[$ ...) के लिए -> .replaceAll (" [^ \\ d।] "," ",) को बदलने के बाद से; अन्य मुद्रा के अलावा आपके पास सिर्फ अन्य वर्ण हैं; $, जैसे मेरे मामले में R $ (ब्राज़ीलियाई) था
— user2582318

1
क्षमा करें, सही सुझाव यह है -> .replaceAll("[^0-9]", ""), ऊपर वाले की सीमा 9.999.999 -_- की है
— user2582318

21

यहाँ मेरा रिवाज है CurrencyEditText

import android.content.Context;import android.graphics.Rect;import android.text.Editable;import android.text.InputFilter;import android.text.InputType;import android.text.TextWatcher;
import android.util.AttributeSet;import android.widget.EditText;import java.math.BigDecimal;import java.math.RoundingMode;
import java.text.DecimalFormat;import java.text.DecimalFormatSymbols;
import java.util.Locale;

/**
 * Some note <br/>
 * <li>Always use locale US instead of default to make DecimalFormat work well in all language</li>
 */
public class CurrencyEditText extends android.support.v7.widget.AppCompatEditText {
    private static String prefix = "VND ";
    private static final int MAX_LENGTH = 20;
    private static final int MAX_DECIMAL = 3;
    private CurrencyTextWatcher currencyTextWatcher = new CurrencyTextWatcher(this, prefix);

    public CurrencyEditText(Context context) {
        this(context, null);
    }

    public CurrencyEditText(Context context, AttributeSet attrs) {
        this(context, attrs, android.support.v7.appcompat.R.attr.editTextStyle);
    }

    public CurrencyEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
        this.setHint(prefix);
        this.setFilters(new InputFilter[] { new InputFilter.LengthFilter(MAX_LENGTH) });
    }

    @Override
    protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
        super.onFocusChanged(focused, direction, previouslyFocusedRect);
        if (focused) {
            this.addTextChangedListener(currencyTextWatcher);
        } else {
            this.removeTextChangedListener(currencyTextWatcher);
        }
        handleCaseCurrencyEmpty(focused);
    }

    /**
     * When currency empty <br/>
     * + When focus EditText, set the default text = prefix (ex: VND) <br/>
     * + When EditText lose focus, set the default text = "", EditText will display hint (ex:VND)
     */
    private void handleCaseCurrencyEmpty(boolean focused) {
        if (focused) {
            if (getText().toString().isEmpty()) {
                setText(prefix);
            }
        } else {
            if (getText().toString().equals(prefix)) {
                setText("");
            }
        }
    }

    private static class CurrencyTextWatcher implements TextWatcher {
        private final EditText editText;
        private String previousCleanString;
        private String prefix;

        CurrencyTextWatcher(EditText editText, String prefix) {
            this.editText = editText;
            this.prefix = prefix;
        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            // do nothing
        }

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

        @Override
        public void afterTextChanged(Editable editable) {
            String str = editable.toString();
            if (str.length() < prefix.length()) {
                editText.setText(prefix);
                editText.setSelection(prefix.length());
                return;
            }
            if (str.equals(prefix)) {
                return;
            }
            // cleanString this the string which not contain prefix and ,
            String cleanString = str.replace(prefix, "").replaceAll("[,]", "");
            // for prevent afterTextChanged recursive call
            if (cleanString.equals(previousCleanString) || cleanString.isEmpty()) {
                return;
            }
            previousCleanString = cleanString;

            String formattedString;
            if (cleanString.contains(".")) {
                formattedString = formatDecimal(cleanString);
            } else {
                formattedString = formatInteger(cleanString);
            }
            editText.removeTextChangedListener(this); // Remove listener
            editText.setText(formattedString);
            handleSelection();
            editText.addTextChangedListener(this); // Add back the listener
        }

        private String formatInteger(String str) {
            BigDecimal parsed = new BigDecimal(str);
            DecimalFormat formatter =
                    new DecimalFormat(prefix + "#,###", new DecimalFormatSymbols(Locale.US));
            return formatter.format(parsed);
        }

        private String formatDecimal(String str) {
            if (str.equals(".")) {
                return prefix + ".";
            }
            BigDecimal parsed = new BigDecimal(str);
            // example pattern VND #,###.00
            DecimalFormat formatter = new DecimalFormat(prefix + "#,###." + getDecimalPattern(str),
                    new DecimalFormatSymbols(Locale.US));
            formatter.setRoundingMode(RoundingMode.DOWN);
            return formatter.format(parsed);
        }

        /**
         * It will return suitable pattern for format decimal
         * For example: 10.2 -> return 0 | 10.23 -> return 00, | 10.235 -> return 000
         */
        private String getDecimalPattern(String str) {
            int decimalCount = str.length() - str.indexOf(".") - 1;
            StringBuilder decimalPattern = new StringBuilder();
            for (int i = 0; i < decimalCount && i < MAX_DECIMAL; i++) {
                decimalPattern.append("0");
            }
            return decimalPattern.toString();
        }

        private void handleSelection() {
            if (editText.getText().length() <= MAX_LENGTH) {
                editText.setSelection(editText.getText().length());
            } else {
                editText.setSelection(MAX_LENGTH);
            }
        }
    }
}

XML में इसका उपयोग करें

 <...CurrencyEditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />

आपको अपनी परियोजना के लिए उपयुक्त 2 निरंतर नीचे संपादित करना चाहिए

private static String prefix = "VND ";
private static final int MAX_DECIMAL = 3;

यहाँ छवि विवरण दर्ज करें

जीथब पर डेमो


2
ये जबरदस्त है!
— यट्रेल

1
मैंने पाया कि अधिकतम दशमलव स्थानों तक पहुँचने के लिए टाइप करने के बाद, 5-9 की संख्या में प्रवेश करने की कोशिश करने से अंतिम दशमलव स्थान 1 से बढ़ जाएगा ... यह गोल हो रहा है! मेरा फिक्स विधि formatter.setRoundingMode(RoundingMode.DOWN);में कॉल करना था formatDecimal।
— बब्लू

@bwicks इस समस्या को खोजने के लिए बहुत बहुत धन्यवाद। मैंने
— फान वान

VND की मुद्रा प्रतीक चिन्ह कैसे लगाएं?
— मयूर कर्मूर

1
एक और सुधार का विचार: यदि उपयोगकर्ता प्रवेश करता है $., जब हमें कच्चे मूल्य के रूप में .दोगुना और पार्स मिलता है , तो यह एनएफई देता है। ठीक करने के लिए, मैंने formatDecimal()वापसी की prefix + "0.";और अंदर तक बदल #,###.गया । यह तब भी बेहतर लगता है जब उपयोगकर्ता केवल दशमलव स्थानों में प्रवेश करता है। इसके बजाय के रूप में दिखाता है । #,##0.formatDecimal()$0.25$.25
— गोखन अरीक

13

दरअसल, इससे पहले दिया गया समाधान काम नहीं कर रहा है। यदि आप 100.00 में प्रवेश करना चाहते हैं तो यह काम नहीं करता है।

बदलने के:

double parsed = Double.parseDouble(cleanString);
String formato = NumberFormat.getCurrencyInstance().format((parsed/100));

साथ में:

BigDecimal parsed = new BigDecimal(cleanString).setScale(2,BigDecimal.ROUND_FLOOR).divide(new BigDecimal(100),BigDecimal.ROUND_FLOOR);                
String formato = NumberFormat.getCurrencyInstance().format(parsed);

मुझे कहना होगा कि मैंने अपने कोड के लिए कुछ संशोधन किए हैं। बात यह है कि आपको बिगडेसीमल का उपयोग करना चाहिए


6

मैं Brasil मुद्रा स्वरूपों का उपयोग करने के लिए TextWatcher के साथ वर्ग को बदलता है और मूल्य को संपादित करते समय कर्सर की स्थिति को समायोजित करता है।

सार्वजनिक वर्ग

    निजी EditText editText;

    निजी स्ट्रिंग lastAmount = "";

    निजी int lastCursorPosition = -1;

    पब्लिक मनीटेक्वाटर (EditText editText) {
        उत्तम();
        this.editText = editText;
    }

    @Override
    सार्वजनिक शून्य onTextChanged (CharSequence राशि, int start, int से पहले, int count) {

        अगर (राशि .toString ()। बराबर (lastAmount)) {

            स्ट्रिंग cleanString = clearCurrencyToNumber (amount.toString ());

            प्रयत्न {

                स्ट्रिंग फ़ॉर्मैटेडअमाउंट = ट्रांस्फ़ॉर्मटोक्यूरिटी (क्लीनस्ट्रिंग);
                editText.removeTextChangedListener (this);
                editText.setText (formattedAmount);
                editText.setSelection (formattedAmount.length ());
                editText.addTextChangedListener (this);

                if (lastCursorPosition! = lastAmount.length () && lastCursorPosition! = -1) {{
                    int lengthDelta = formattedAmount.length () - lastAmount.length ();
                    int newCursorOffset = अधिकतम (0, मिनट (स्वरूपित .mount.length), lastCursorPosition + lengthDelta));
                    editText.setSelection (newCursorOffset);
                }
            } पकड़ (अपवाद ई) {
               // कुछ लॉग करें
            }
        }
    }

    @Override
    सार्वजनिक शून्य afterTextChanged (संपादन योग्य) {
    }

    @Override
    सार्वजनिक शून्य से पहले कस्टमचार्ज (चार साक्षरता, इंट शुरू, इंट काउंट, इंट आफ्टर) {
        स्ट्रिंग मूल्य = s.toString ();
        if (! value.equals ( "")) {
            स्ट्रिंग cleanString = clearCurrencyToNumber (मान);
            स्ट्रिंग फ़ॉर्मैटेडअमाउंट = ट्रांस्फ़ॉर्मटोक्यूरिटी (क्लीनस्ट्रिंग);
            lastAmount = स्वरूपित किया हुआ;
            lastCursorPosition = editText.getSelectionStart ();
        }
    }

    सार्वजनिक स्थैतिक स्ट्रिंग ClearCurrencyToNumber (स्ट्रिंग मुद्रावैल्यू) {
        स्ट्रिंग परिणाम = अशक्त;

        अगर (करेंसीवायु == अशक्त) {
            परिणाम = "";
        } अन्य {
            परिणाम = CurrencyValue.replaceAll ("[(az) | (AZ) | ($ ($),]", "");
        }
        वापसी परिणाम;
    }

    सार्वजनिक स्थिर बूलियन है CurrencyValue (स्ट्रिंग मुद्रावायु, बूलियन podeSerZero) {
        बूलियन परिणाम;

        if (करेंसीवैल्यू == null || CurrencyValue.length () == 0) {
            परिणाम = असत्य;
        } अन्य {
            अगर (podeSerZero && currencyValue.equals ("0,00")) {
                परिणाम = असत्य;
            } अन्य {
                परिणाम = सत्य;
            }
        }
        वापसी परिणाम;
    }

    सार्वजनिक स्थैतिक स्ट्रिंग ट्रांसफ़ॉर्मटेरिकेंसी (स्ट्रिंग मान) {
        double parsed = Double.parseDouble (मान);
        स्ट्रिंग स्वरूपित = NumberFormat.getCurrencyInstance (नया स्थान ("pt", "" "))। प्रारूप ((पार्स / 100));
        स्वरूपित = स्वरूपित .replaceAll ("[^ (0-9) (;,)]", "");
        स्वरूपित वापसी;
    }
}

इस पंक्ति में "int newCursorOffset = max (0, min (formattedAmount.length), lastCursorPosition + lengthDelta);" किस प्रकार की वस्तु अधिकतम और न्यूनतम है?
— आर्थर मेलो

2
@ArthurMelo इसका, Math.max, Math.min कोड को धन्यवाद, और यह एडिटेक्स से अल्पविराम को हटाते समय विफल जैसा दिखता है।
— मार्कोस वास्कोनसेलोस

4

मैंने गुइलहर्म्स उत्तर पर बनाया था, लेकिन मैं कर्सर की स्थिति को संरक्षित करता हूं और अलग-अलग अवधि का भी इलाज करता हूं - इस तरह से यदि कोई उपयोगकर्ता अवधि के बाद टाइप कर रहा है, तो यह संख्याओं को प्रभावित नहीं करता है इससे पहले कि मुझे लगता है कि यह एक बहुत ही चिकनी इनपुट देता है ।

    [yourtextfield].addTextChangedListener(new TextWatcher()
    {
        NumberFormat currencyFormat = NumberFormat.getCurrencyInstance();
        private String current = "";

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count)
        {
            if(!s.toString().equals(current))
            {
                   [yourtextfield].removeTextChangedListener(this);

                   int selection = [yourtextfield].getSelectionStart();


                   // We strip off the currency symbol
                   String replaceable = String.format("[%s,\\s]", NumberFormat.getCurrencyInstance().getCurrency().getSymbol());
                   String cleanString = s.toString().replaceAll(replaceable, "");

                   double price;

                   // Parse the string                     
                   try
                   {
                       price = Double.parseDouble(cleanString);
                   }
                   catch(java.lang.NumberFormatException e)
                   {
                       price = 0;
                   }

                   // If we don't see a decimal, then the user must have deleted it.
                   // In that case, the number must be divided by 100, otherwise 1
                   int shrink = 1;
                   if(!(s.toString().contains(".")))
                   {
                       shrink = 100;
                   }

                   // Reformat the number
                   String formated = currencyFormat.format((price / shrink));

                   current = formated;
                   [yourtextfield].setText(formated);
                   [yourtextfield].setSelection(Math.min(selection, [yourtextfield].getText().length()));

                   [yourtextfield].addTextChangedListener(this);
                }
        }


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

        }


        @Override
        public void afterTextChanged(Editable s)
        {
        }
    });

यह मेरी बहुत मदद करता है। शुक्रिया @genixpro
— हरिन ककलोटर

मुझे आपका विचार पसंद है, लेकिन यह आसान लग रहा है यदि आप कर्सर के बाद अंकों की संख्या को बचाते हैं, तो सेटस्लेक्शन (लंबाई - बाद)।
— अल्फा हुआंग

बहुत ही रोचक! बदली का उपयोग करना मेरे भौतिक उपकरण पर काम करता है, लेकिन यह एमुलेटर पर काम नहीं करता है।
— एलिटिव ओलिवेरा

4

हालाँकि यहाँ बहुत सारे उत्तर हैं, फिर भी मैं इस कोड को साझा करना चाहूँगा जो मुझे यहाँ मिला, क्योंकि मुझे लगता है कि इसका सबसे मजबूत और स्वच्छ उत्तर है।

class CurrencyTextWatcher implements TextWatcher {

    boolean mEditing;

    public CurrencyTextWatcher() {
        mEditing = false;
    }

    public synchronized void afterTextChanged(Editable s) {
        if(!mEditing) {
            mEditing = true;

            String digits = s.toString().replaceAll("\\D", "");
            NumberFormat nf = NumberFormat.getCurrencyInstance();
            try{
                String formatted = nf.format(Double.parseDouble(digits)/100);
                s.replace(0, s.length(), formatted);
            } catch (NumberFormatException nfe) {
                s.clear();
            }

            mEditing = false;
        }
    }

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

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

}

आशा करता हूँ की ये काम करेगा।


उस पट्टी को दशमलव बिंदु से बाहर नहीं करेंगे? तो तब आप $ 100.00 और $ 10,000 के बीच का अंतर नहीं बता पाएंगे - जब तक कि मुझे कुछ याद न हो।
— nasch

2
यह सही जवाब है! मेरे लिए काम किया। मेरा, बस इस बारे में सोचें कि मैंने उन उत्तरों पर कितना समय बिताया और अंत में नीचे स्क्रॉल किया और मुझे जो चाहिए वह मिला।
— जीई रोंग

मुझे खुशी है कि इसने आपकी मदद की।
— कायनात एन

@nasch यह एक TextWatcher है और यह टेक्स्ट को उपयोगकर्ता प्रकारों के रूप में प्रारूपित करता है जो आपके द्वारा उल्लिखित मामले को रोकता है।
— कायवन एन

@KayvanN मुझे पता है कि एक TextWatcher क्या है। replaceAll("\\D", "")वह सब कुछ हटा देगा जो एक अंक नहीं है, इसलिए "$ 100.00" और "$ 10,000" दोनों "10000" हो जाते हैं। ऐसा लगता है कि आप सेंट को शामिल करने के लिए इनपुट पर भरोसा कर रहे हैं। तो अगर यह गारंटी है, महान है, लेकिन अगर मुझे नहीं लगता कि समस्याएं होने जा रही हैं।
— nasch

4

ठीक है, यहां करेंसी फॉर्मेट, डिलीट-बैकवर्ड कीस्ट्रोक से निपटने का बेहतर तरीका है। कोड ऊपर @androidcurious 'कोड पर आधारित है ... लेकिन, पिछड़े-विलोपन से संबंधित कुछ समस्याओं और कुछ पार्स अपवादों से संबंधित है: http://miguelt.blogspot.ca/2013/01/textwatcher-for-currency-masksformatting । html [अद्यतन] पिछले समाधान में कुछ समस्याएं थीं ... यह एक बेहतर समाधान है: http://miguelt.blogspot.ca/2013/02/update-textwatcher-for-currency.html और ... यहाँ हैं विवरण:

यह दृष्टिकोण बेहतर है क्योंकि यह पारंपरिक Android तंत्र का उपयोग करता है। विचार उपयोगकर्ता के मौजूद होने के बाद मूल्यों को प्रारूपित करने के लिए है।

संख्यात्मक मानों को प्रतिबंधित करने के लिए एक InputFilter को परिभाषित करें - यह ज्यादातर मामलों में आवश्यक है क्योंकि स्क्रीन लंबे समय तक संपादित करने के लिए पर्याप्त नहीं है। यह एक स्थिर आंतरिक वर्ग या सिर्फ एक सादा वर्ग हो सकता है:

/** Numeric range Filter. */
class NumericRangeFilter implements InputFilter {
    /** Maximum value. */
    private final double maximum;
    /** Minimum value. */
    private final double minimum;
    /** Creates a new filter between 0.00 and 999,999.99. */
    NumericRangeFilter() {
        this(0.00, 999999.99);
    }
    /** Creates a new filter.
     * @param p_min Minimum value.
     * @param p_max Maximum value. 
     */
    NumericRangeFilter(double p_min, double p_max) {
        maximum = p_max;
        minimum = p_min;
    }
    @Override
    public CharSequence filter(
            CharSequence p_source, int p_start,
            int p_end, Spanned p_dest, int p_dstart, int p_dend
    ) {
        try {
            String v_valueStr = p_dest.toString().concat(p_source.toString());
            double v_value = Double.parseDouble(v_valueStr);
            if (v_value<=maximum && v_value>=minimum) {
                // Returning null will make the EditText to accept more values.
                return null;
            }
        } catch (NumberFormatException p_ex) {
            // do nothing
        }
        // Value is out of range - return empty string.
        return "";
    }
}

एक वर्ग (आंतरिक स्थिर या सिर्फ एक वर्ग) को परिभाषित करें जो View.OnFocusChangeListener को लागू करेगा। ध्यान दें कि मैं यूटिल्स क्लास का उपयोग कर रहा हूं - कार्यान्वयन "एमाउंट, टैक्स" पर पाया जा सकता है।

/** Used to format the amount views. */
class AmountOnFocusChangeListener implements View.OnFocusChangeListener {
    @Override
    public void onFocusChange(View p_view, boolean p_hasFocus) {
        // This listener will be attached to any view containing amounts.
        EditText v_amountView = (EditText)p_view;
        if (p_hasFocus) {
            // v_value is using a currency mask - transfor over to cents.
            String v_value = v_amountView.getText().toString();
            int v_cents = Utils.parseAmountToCents(v_value);
            // Now, format cents to an amount (without currency mask)
            v_value = Utils.formatCentsToAmount(v_cents);
            v_amountView.setText(v_value);
            // Select all so the user can overwrite the entire amount in one shot.
            v_amountView.selectAll();
        } else {
            // v_value is not using a currency mask - transfor over to cents.
            String v_value = v_amountView.getText().toString();
            int v_cents = Utils.parseAmountToCents(v_value);
            // Now, format cents to an amount (with currency mask)
            v_value = Utils.formatCentsToCurrency(v_cents);
            v_amountView.setText(v_value);
        }
    }
}

यह कक्षा मानक तंत्रों पर निर्भर करते हुए संपादन करते समय मुद्रा प्रारूप को हटा देगी। जब उपयोगकर्ता बाहर निकलता है, तो मुद्रा प्रारूप फिर से लागू होता है।

उदाहरणों की संख्या को कम करने के लिए कुछ स्थिर चर को परिभाषित करना बेहतर है:

   static final InputFilter[] FILTERS = new InputFilter[] {new NumericRangeFilter()};
   static final View.OnFocusChangeListener ON_FOCUS = new AmountOnFocusChangeListener();

अंत में, onCreateView (...) के भीतर:

   EditText mAmountView = ....
   mAmountView.setFilters(FILTERS);
   mAmountView.setOnFocusChangeListener(ON_FOCUS);

आप किसी भी संख्या में EditText के विचारों पर फ़िल्टर और ON_FOCUS का पुन: उपयोग कर सकते हैं।

यहाँ बर्तन वर्ग है:

public class Utils {

   private static final NumberFormat FORMAT_CURRENCY = NumberFormat.getCurrencyInstance();
   /** Parses an amount into cents.
    * @param p_value Amount formatted using the default currency. 
    * @return Value as cents.
    */
   public static int parseAmountToCents(String p_value) {
       try {
           Number v_value = FORMAT_CURRENCY.parse(p_value);
           BigDecimal v_bigDec = new BigDecimal(v_value.doubleValue());
           v_bigDec = v_bigDec.setScale(2, BigDecimal.ROUND_HALF_UP);
           return v_bigDec.movePointRight(2).intValue();
       } catch (ParseException p_ex) {
           try {
               // p_value doesn't have a currency format.
               BigDecimal v_bigDec = new BigDecimal(p_value);
               v_bigDec = v_bigDec.setScale(2, BigDecimal.ROUND_HALF_UP);
               return v_bigDec.movePointRight(2).intValue();
           } catch (NumberFormatException p_ex1) {
               return -1;
           }
       }
   }
   /** Formats cents into a valid amount using the default currency.
    * @param p_value Value as cents 
    * @return Amount formatted using a currency.
    */
   public static String formatCentsToAmount(int p_value) {
       BigDecimal v_bigDec = new BigDecimal(p_value);
       v_bigDec = v_bigDec.setScale(2, BigDecimal.ROUND_HALF_UP);
       v_bigDec = v_bigDec.movePointLeft(2);
       String v_currency = FORMAT_CURRENCY.format(v_bigDec.doubleValue());
       return v_currency.replace(FORMAT_CURRENCY.getCurrency().getSymbol(), "").replace(",", "");
   }
   /** Formats cents into a valid amount using the default currency.
    * @param p_value Value as cents 
    * @return Amount formatted using a currency.
    */
   public static String formatCentsToCurrency(int p_value) {
       BigDecimal v_bigDec = new BigDecimal(p_value);
       v_bigDec = v_bigDec.setScale(2, BigDecimal.ROUND_HALF_UP);
       v_bigDec = v_bigDec.movePointLeft(2);
       return FORMAT_CURRENCY.format(v_bigDec.doubleValue());
   }

}

जबकि यह सैद्धांतिक रूप से प्रश्न का उत्तर दे सकता है, हम चाहेंगे कि आप अपने उत्तर में लिंक किए गए लेख के आवश्यक भागों को शामिल करें, और संदर्भ के लिए लिंक प्रदान करें । ऐसा करने में नाकाम रहने से लिंक सड़ने का खतरा पैदा हो जाता है।
— केव

मुझे java.lang.NumberFormatException मिल रही है: अमान्य डबल: "$ 12,345.00" जब संपादन पाठ खो जाता है। इसे कैसे जोड़ेंगे।
— माधवन

4

मैंने निम्नलिखित संस्करण बनाने के लिए अंकों को छोड़कर सभी वर्णों को हटाने के लिए कार्यान्वयन नथन लेह संदर्भित और कायवन एन और user2582318 के सुझाए गए regex का उपयोग किया:

fun EditText.addCurrencyFormatter() {

    // Reference: /programming/5107901/better-way-to-format-currency-input-edittext/29993290#29993290
    this.addTextChangedListener(object: TextWatcher {

        private var current = ""

        override fun afterTextChanged(s: Editable?) {
        }

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

        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {

            if (s.toString() != current) {
                this@addCurrencyFormatter.removeTextChangedListener(this)
                // strip off the currency symbol

                // Reference for this replace regex: /programming/5107901/better-way-to-format-currency-input-edittext/28005836#28005836
                val cleanString = s.toString().replace("\\D".toRegex(), "")
                val parsed = if (cleanString.isBlank()) 0.0 else cleanString.toDouble()
                // format the double into a currency format
                val formated = NumberFormat.getCurrencyInstance()
                        .format(parsed / 100)

                current = formated
                this@addCurrencyFormatter.setText(formated)
                this@addCurrencyFormatter.setSelection(formated.length)

                this@addCurrencyFormatter.addTextChangedListener(this)
            }
        }
    })

}

यह कोटलिन में एक एक्सटेंशन फंक्शन है, जो एडिटटेक्स्ट के TextChangedListener में TextWatcher जोड़ता है।

इसका उपयोग करने के लिए, बस:

yourEditText = (EditText) findViewById(R.id.edit_text_your_id);
yourEditText.addCurrencyFormatter()

मुझे उम्मीद है यह मदद करेगा।


3

मैंने इसे यहां से प्राप्त किया और इसे पुर्तगाली मुद्रा प्रारूप का अनुपालन करने के लिए बदल दिया।

import java.text.NumberFormat;
import java.util.Currency;
import java.util.Locale;

import android.text.Editable;
import android.text.TextWatcher;
import android.widget.EditText;

public class CurrencyTextWatcher implements TextWatcher {

    private String current = "";
    private int index;
    private boolean deletingDecimalPoint;
    private final EditText currency;

    public CurrencyTextWatcher(EditText p_currency) {
        currency = p_currency;
    }


    @Override
    public void beforeTextChanged(CharSequence p_s, int p_start, int p_count, int p_after) {

        if (p_after>0) {
                index = p_s.length() - p_start;
            } else {
                index = p_s.length() - p_start - 1;
            }
            if (p_count>0 && p_s.charAt(p_start)==',') {
                deletingDecimalPoint = true;
            } else {
                deletingDecimalPoint = false;
            }

    }

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

    }

    @Override
    public void afterTextChanged(Editable p_s) {


         if(!p_s.toString().equals(current)){
                currency.removeTextChangedListener(this);
                if (deletingDecimalPoint) {
                    p_s.delete(p_s.length()-index-1, p_s.length()-index);
                }
                // Currency char may be retrieved from  NumberFormat.getCurrencyInstance()
                String v_text = p_s.toString().replace("€","").replace(",", "");
                v_text = v_text.replaceAll("\\s", "");
                double v_value = 0;
                if (v_text!=null && v_text.length()>0) {
                    v_value = Double.parseDouble(v_text);
                }
                // Currency instance may be retrieved from a static member.
                NumberFormat numberFormat = NumberFormat.getCurrencyInstance(new Locale("pt", "PT"));
                String v_formattedValue = numberFormat.format((v_value/100));
                current = v_formattedValue;
                currency.setText(v_formattedValue);
                if (index>v_formattedValue.length()) {
                    currency.setSelection(v_formattedValue.length());
                } else {
                    currency.setSelection(v_formattedValue.length()-index);
                }
                // include here anything you may want to do after the formatting is completed.
                currency.addTextChangedListener(this);
             }
    }

}

लेआउट। Xml

<EditText
    android:id="@+id/edit_text_your_id"
    ...
    android:text="0,00 €"
    android:inputType="numberDecimal"
    android:digits="0123456789" />

काम पर लग जाओ

    yourEditText = (EditText) findViewById(R.id.edit_text_your_id);
    yourEditText.setRawInputType(Configuration.KEYBOARD_12KEY);
    yourEditText.addTextChangedListener(new CurrencyTextWatcher(yourEditText));

2

मेरे लिए यह इस तरह काम करता था

 public void onTextChanged(CharSequence s, int start,
                    int before, int count) {
                if(!s.toString().matches("^\\$(\\d{1,3}(\\,\\d{3})*|(\\d+))(\\.\\d{2})?$"))
                {
                    String userInput= ""+s.toString().replaceAll("[^\\d]", "");
                    if (userInput.length() > 2) {
                        Float in=Float.parseFloat(userInput);
                        price = Math.round(in); // just to get an Integer
                        //float percen = in/100;
                        String first, last;
                        first = userInput.substring(0, userInput.length()-2);
                        last = userInput.substring(userInput.length()-2);
                        edEx1.setText("$"+first+"."+last);
                        Log.e(MainActivity.class.toString(), "first: "+first + " last:"+last);
                        edEx1.setSelection(edEx1.getText().length());
                    }
                }
            }

2

InputFilter इंटरफ़ेस का उपयोग करना बेहतर है। रेगेक्स का उपयोग करके किसी भी तरह के इनपुट को संभालना बहुत आसान है। मुद्रा इनपुट प्रारूप के लिए मेरा समाधान:

public class CurrencyFormatInputFilter implements InputFilter {

Pattern mPattern = Pattern.compile("(0|[1-9]+[0-9]*)(\\.[0-9]{1,2})?");

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

String result = 
        dest.subSequence(0, dstart)
        + source.toString() 
        + dest.subSequence(dend, dest.length());

Matcher matcher = mPattern.matcher(result);

if (!matcher.matches()) return dest.subSequence(dstart, dend);

return null;
}
}

मान्य: 0.00, 0.0, 10.00, 111.1
अमान्य: 0, 0.000, 111, 10, 010.00, 01.0

कैसे इस्तेमाल करे:

editText.setFilters(new InputFilter[] {new CurrencyFormatInputFilter()});

1

मैंने इसका उपयोग उपयोगकर्ता को मुद्रा में प्रवेश करने और इसे स्ट्रिंग से इंट में बदलने के लिए db में स्टोर करने और फिर से स्ट्रिंग से वापस बदलने के लिए किया।

https://github.com/nleigh/Restaurant/blob/master/Restaurant/src/uk/co/nathanleigh/restaurant/CurrencyFormat.java


क्या आप अपने उत्तर में मुख्य अवधारणाओं को शामिल कर सकते हैं? अन्यथा यह बहुत अधिक एक लिंक-केवल उत्तर है और विलोपन के लिए प्रवण है ...
— अलेक्जेंडर वोग्ट

1

यदि आपका json मुद्रा क्षेत्र संख्या प्रकार का है (और स्ट्रिंग नहीं) तो यह 3.1, 3.15 या सिर्फ 3. के रूप में आ सकता है क्योंकि json स्वचालित रूप से संख्या क्षेत्रों को गोल कर देता है।

इस मामले में आपको उचित प्रदर्शन के लिए इसे गोल करने की आवश्यकता हो सकती है (और बाद में इनपुट क्षेत्र पर मास्क का उपयोग करने में सक्षम होने के लिए):

    NumberFormat nf = NumberFormat.getCurrencyInstance();

    float value = 200 // it can be 200, 200.3 or 200.37, BigDecimal will take care
    BigDecimal valueAsBD = BigDecimal.valueOf(value);
    valueAsBD.setScale(2, BigDecimal.ROUND_HALF_UP);

    String formated = nf.format(valueAsBD);

इसकी आवश्यकता क्यों है?

सभी उत्तर मुद्रा सिंबल को हटाने के लिए इंगित करते हैं जब टाइप करते हुए आप सेंट प्राप्त कर रहे हैं और इसलिए dolar + cents / 100 = dolar, सेंट तैयार कर रहे हैं। लेकिन अगर आपका जसन मुद्रा क्षेत्र एक संख्या प्रकार है (और स्ट्रिंग नहीं है) तो यह आपके सेंट को गोल कर देगा, यह 3, 3.1 या 3.15 हो सकता है।


1
वास्तव में मुझे जो चाहिए था। धन्यवाद!
— एरिक एंगलहार्ट

come as 3.1 , 3.15 or just 3. Because json automatically round number fields- यह गोलाई के साथ कुछ भी सामान्य नहीं मिला !
— Marcin Orlowski

1

एक और दृष्टिकोण, लेकिन गिलहर्मे जवाब पर आधारित है । यह दृष्टिकोण तब उपयोगी है जब आपके देश का स्थान उपलब्ध नहीं है, या यदि आप कस्टम मुद्रा प्रतीकों का उपयोग करना चाहते हैं। यह कार्यान्वयन केवल सकारात्मक गैर-दशमलव के लिए है।

यह कोड कोटलिन में है, जिसके लिए पहला प्रतिनिधि setMaskingMoneyहैEditText

fun EditText.setMaskingMoney(currencyText: String) {
    this.addTextChangedListener(object: MyTextWatcher{
        val editTextWeakReference: WeakReference<EditText> = WeakReference<EditText>(this@setMaskingMoney)
        override fun afterTextChanged(editable: Editable?) {
            val editText = editTextWeakReference.get() ?: return
            val s = editable.toString()
            editText.removeTextChangedListener(this)
            val cleanString = s.replace("[Rp,. ]".toRegex(), "")
            val newval = currencyText + cleanString.monetize()

            editText.setText(newval)
            editText.setSelection(newval.length)
            editText.addTextChangedListener(this)
        }
    })
}

फिर MyTextWatcherइंटरफ़ेस से बढ़ाया जाना चाहिए TextWatcher। चूँकि हमें केवल afterTextChangedविधि की आवश्यकता होती है, अन्य तरीकों की आवश्यकता इस इंटरफेस में अधिक होनी चाहिए

interface MyTextWatcher: TextWatcher {
    override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
    override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
}

और विमुद्रीकरण विधि है:

fun String.monetize(): String = if (this.isEmpty()) "0"
    else DecimalFormat("#,###").format(this.replace("[^\\d]".toRegex(),"").toLong())

पूर्ण कार्यान्वयन:

fun EditText.setMaskingMoney(currencyText: String) {
    this.addTextChangedListener(object: MyTextWatcher{
        val editTextWeakReference: WeakReference<EditText> = WeakReference<EditText>(this@setMaskingMoney)
        override fun afterTextChanged(editable: Editable?) {
            val editText = editTextWeakReference.get() ?: return
            val s = editable.toString()
            editText.removeTextChangedListener(this)
            val cleanString = s.replace("[Rp,. ]".toRegex(), "")
            val newval = currencyText + cleanString.monetize()

            editText.setText(newval)
            editText.setSelection(newval.length)
            editText.addTextChangedListener(this)
        }
    })
}

interface MyTextWatcher: TextWatcher {
    override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
    override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
}


fun String.monetize(): String = if (this.isEmpty()) "0"
    else DecimalFormat("#,###").format(this.replace("[^\\d]".toRegex(),"").toLong())

और कहीं ऑनक्रेट विधि:

yourTextView.setMaskingMoney("Rp. ")

1

बहुत अधिक खोज और विफलताओं के बाद डबल्स, बिगडेकिमल्स और इतने पर, मैंने यह कोड बनाया है। यह प्लग एंड प्ले का काम करता है। इसकी कोटलिन में। तो, दूसरों की मदद करने के लिए मेरी तरह अटक, चलो चलते हैं।

कोड मूल रूप से एक फ़ंक्शन है जो एक टेक्स्टवॉकर रखेगा और कोमा को सही जगह पर समायोजित करेगा।

सबसे पहले, इस समारोह बनाएँ:

fun CurrencyWatcher( editText:EditText) {

    editText.addTextChangedListener(object : TextWatcher {
        //this will prevent the loop
        var changed: Boolean = false

        override fun afterTextChanged(p0: Editable?) {
            changed = false

        }

        override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {

            editText.setSelection(p0.toString().length)
        }

        @SuppressLint("SetTextI18n")
        override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
            if (!changed) {
                changed = true

                var str: String = p0.toString().replace(",", "").trim()
                var element0: String = str.elementAt(0).toString()
                var element1: String = "x"
                var element2: String = "x"
                var element3: String = "x"
                var element4: String = "x"
                var element5: String = "x"
                var element6: String = "x"

                //this variables will store each elements of the initials data for the case we need to move this numbers like: 0,01 to 0,11 or 0,11 to 0,01
                if (str.length >= 2) {
                    element1 = str.elementAt(1).toString()
                }
                if (str.length >= 3) {
                    element2 = str.elementAt(2).toString()
                }

                editText.removeTextChangedListener(this)


                //this first block of code will take care of the case
                //where the number starts with 0 and needs to adjusta the 0 and the "," place
                if (str.length == 1) {
                    str = "0,0" + str
                    editText.setText(str)

                } else if (str.length <= 3 && str == "00") {

                    str = "0,00"
                    editText.setText(str)
                    editText.setSelection(str.length)
                } else if (element0 == "0" && element1 == "0" && element2 == "0") {
                    str = str.replace("000", "")
                    str = "0,0" + str
                    editText.setText(str)
                } else if (element0 == "0" && element1 == "0" && element2 != "0") {
                    str = str.replace("00", "")
                    str = "0," + str
                    editText.setText(str)
                } else {

                    //This block of code works with the cases that we need to move the "," only because the value is bigger
                    //lets get the others elements
                    if (str.length >= 4) {
                        element3 = str.elementAt(3).toString()
                    }
                    if (str.length >= 5) {
                        element4 = str.elementAt(4).toString()
                    }
                    if (str.length >= 6) {
                        element5 = str.elementAt(5).toString()
                    }
                    if (str.length == 7) {
                        element6 = str.elementAt(6).toString()
                    }


                    if (str.length >= 4 && element0 != "0") {

                        val sb: StringBuilder = StringBuilder(str)
                        //set the coma in right place
                        sb.insert(str.length - 2, ",")
                        str = sb.toString()
                    }

                    //change the 0,11 to 1,11
                    if (str.length == 4 && element0 == "0") {

                        val sb: StringBuilder = StringBuilder(str)
                        //takes the initial 0 out
                        sb.deleteCharAt(0);
                        str = sb.toString()

                        val sb2: StringBuilder = StringBuilder(str)
                        sb2.insert(str.length - 2, ",")
                        str = sb2.toString()
                    }

                    //this will came up when its like 11,11 and the user delete one, so it will be now 1,11
                    if (str.length == 3 && element0 != "0") {
                        val sb: StringBuilder = StringBuilder(str)
                        sb.insert(str.length - 2, ",")
                        str = sb.toString()
                    }

                    //came up when its like 0,11 and the user delete one, output will be 0,01
                    if (str.length == 2 && element0 == "0") {
                        val sb: StringBuilder = StringBuilder(str)
                        //takes 0 out
                        sb.deleteCharAt(0);
                        str = sb.toString()

                        str = "0,0" + str

                    }

                    //came up when its 1,11 and the user delete, output will be 0,11
                    if (str.length == 2 && element0 != "0") {
                        val sb: StringBuilder = StringBuilder(str)
                        //retira o 0 da frente
                        sb.insert(0, "0,")
                        str = sb.toString()

                    }


                    editText.setText(str)
                }

                //places the selector at the end to increment the number
                editText.setSelection(str.length)
                editText.addTextChangedListener(this)
            }

        }
    })
}

और फिर आप इस फ़ंक्शन को इस तरह कहते हैं

val etVal:EditText = findViewById(R.id.etValue)

CurrencyWatcher(etVal)

0

अलग अलग तरीकों पर StackOverflow पदों के सबसे को देखने के बाद का उपयोग कर इस लक्ष्य को हासिल करने के लिए एक TextWatcher, InputFilterया जैसे पुस्तकालय CurrencyEditText मैं इस सरल एक का उपयोग कर समाधान पर बसे गया हैOnFocusChangeListener ।

EditTextजब इसे फोकस किया जाता है तो लॉजिक को एक नंबर पर पार्स करना होता है और फ़ोकस खोने पर इसे वापस फॉर्मेट करना होता है।

amount.setOnFocusChangeListener(new View.OnFocusChangeListener() {
        @Override
        public void onFocusChange(View view, boolean hasFocus) {
            Number numberAmount = 0f;
            try {
                numberAmount = Float.valueOf(amount.getText().toString());
            } catch (NumberFormatException e1) {
                e1.printStackTrace();
                try {
                    numberAmount = NumberFormat.getCurrencyInstance().parse(amount.getText().toString());
                } catch (ParseException e2) {
                    e2.printStackTrace();
                }
            }
            if (hasFocus) {
                amount.setText(numberAmount.toString());
            } else {
                amount.setText(NumberFormat.getCurrencyInstance().format(numberAmount));
            }
        }
    });

0

मैंने एक कोटलिन + आरएक्स संस्करण लागू किया है।

यह ब्राजील की मुद्रा के लिए है (जैसे 1,500.00 - 5,21 - 192,90), लेकिन आप आसानी से अन्य प्रारूपों के लिए अनुकूलित कर सकते हैं।

आशा है कि किसी और को यह मददगार लगे।

RxTextView
            .textChangeEvents(fuel_price) // Observe text event changes
            .filter { it.text().isNotEmpty() } // do not accept empty text when event first fires
            .flatMap {
                val onlyNumbers = Regex("\\d+").findAll(it.text()).fold(""){ acc:String,it:MatchResult -> acc.plus(it.value)}
                Observable.just(onlyNumbers)
            }
            .distinctUntilChanged()
            .map { it.trimStart('0') }
            .map { when (it.length) {
                        1-> "00"+it
                        2-> "0"+it
                        else -> it }
            }
            .subscribe {
                val digitList = it.reversed().mapIndexed { i, c ->
                    if ( i == 2 ) "${c},"
                    else if ( i < 2 ) c
                    else if ( (i-2)%3==0 ) "${c}." else c
                }

                val currency = digitList.reversed().fold(""){ acc,it -> acc.toString().plus(it) }
                fuel_price.text = SpannableStringBuilder(currency)
                fuel_price.setSelection(currency.length)
            }

0

CurrencyTextWatcher.java

public class CurrencyTextWatcher implements TextWatcher {

    private final static String DS = "."; //Decimal Separator
    private final static String TS = ","; //Thousands Separator
    private final static String NUMBERS = "0123456789"; //Numbers
    private final static int MAX_LENGTH = 13; //Maximum Length

    private String format;

    private DecimalFormat decimalFormat;
    private EditText editText;

    public CurrencyTextWatcher(EditText editText) {
        String pattern = "###" + TS + "###" + DS + "##";
        decimalFormat = new DecimalFormat(pattern);
        this.editText = editText;
        this.editText.setInputType(InputType.TYPE_CLASS_NUMBER);
        this.editText.setKeyListener(DigitsKeyListener.getInstance(NUMBERS + DS));
        this.editText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(MAX_LENGTH)});
    }

    @Override
    public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

    }

    @Override
    public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {

    }

    @Override
    public void afterTextChanged(Editable editable) {

        editText.removeTextChangedListener(this);
        String value = editable.toString();
        if (!value.isEmpty()) {
            value = value.replace(TS, "");
            try {
                format = decimalFormat.format(Double.parseDouble(value));
                format = format.replace("0", "");
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }

            editText.setText(format);
        }

        editText.addTextChangedListener(this);
    }
}

EditTextCurrency.java

public class EditTextCurrency extends AppCompatEditText {
    public EditTextCurrency(Context context) {
        super(context);
    }

    public EditTextCurrency(Context context, AttributeSet attrs) {
        super(context, attrs);
        addTextChangedListener(new CurrencyTextWatcher(this));
    }
}

यहाँ छवि विवरण दर्ज करें


0

यहां बताया गया है कि कैसे मैं एक EditText में एक मुद्रा प्रदर्शित करने में सक्षम था जो कि सभी जगह पागल प्रतीकों के लिए संभावित के बिना उपयोगकर्ता के लिए लागू करना और अच्छी तरह से काम करना आसान था। यह किसी भी स्वरूपण को तब तक करने की कोशिश नहीं करेगा जब तक कि EditText पर ध्यान केंद्रित नहीं किया जाता है। उपयोगकर्ता अभी भी वापस जा सकता है और स्वरूपण को खतरे में डाले बिना कोई भी संपादन कर सकता है। मैं केवल प्रदर्शन के लिए 'स्वरूपित चर' चर का उपयोग करता हूं, और गणना के लिए उपयोग / मूल्य के रूप में 'आइटमप्राइस' चर का उपयोग करता हूं।

ऐसा लगता है कि यह वास्तव में अच्छी तरह से काम कर रहा है, लेकिन मैं केवल कुछ ही हफ्तों के लिए रहा हूं, इसलिए किसी भी रचनात्मक आलोचना का स्वागत है!

Xml में EditText दृश्य के निम्नलिखित गुण हैं:

android:inputType="numberDecimal"

सार्वत्रिक चर:

private String formattedPrice;
private int itemPrice = 0;

ऑनक्रीट विधि में:

EditText itemPriceInput = findViewById(R.id.item_field_price);

itemPriceInput.setOnFocusChangeListener(new View.OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        String priceString = itemPriceInput.getText().toString();

        if (! priceString.equals("")) {
            itemPrice = Double.parseDouble(priceString.replaceAll("[$,]", ""));
            formattedPrice = NumberFormat.getCurrencyInstance().format(itemPrice);
            itemPriceInput.setText(formattedPrice);
        }
    }
});

0

मामले में किसी को RxBinding और Kotlin का उपयोग करने के तरीके में दिलचस्पी है:

var isEditing = false

RxTextView.textChanges(dollarValue)
            .filter { !isEditing }
            .filter { it.isNotBlank() }
            .map { it.toString().filter { it.isDigit() } }
            .map { BigDecimal(it).setScale(2, BigDecimal.ROUND_FLOOR).divide(100.toBigDecimal(), BigDecimal.ROUND_FLOOR) }
            .map { NumberFormat.getCurrencyInstance(Locale("pt", "BR")).format(it) }
            .subscribe {
                isEditing = true
                dollarValue.text = SpannableStringBuilder(it)
                dollarValue.setSelection(it.length)
                isEditing = false
            }

0

स्वीकृत उत्तर के लिए सिर्फ एक अतिरिक्त टिप्पणी। पार्सिंग के कारण edittext फ़ील्ड पर कर्सर ले जाने पर आपको दुर्घटना हो सकती है। मैंने एक कोशिश पकड़ने वाला बयान दिया, लेकिन अपना कोड लागू करें।

@Override public void onTextChanged(CharSequence s, int start, int before, int count) {
        if(!s.toString().equals(current)){
        amountEditText.removeTextChangedListener(this);

            String cleanString = s.toString().replaceAll("[$,.]", "");

            try{
                double parsed = Double.parseDouble(cleanString);
                String formatted = NumberFormat.getCurrencyInstance().format((parsed/100));
                current = formatted;
                amountEditText.setText(formatted);
                amountEditText.setSelection(formatted.length());
            } catch (Exception e) {

            }

            amountEditText.addTextChangedListener(this);
        }
    }

0

आप इन विधियों का उपयोग कर सकते हैं

import android.text.Editable
import android.text.TextWatcher
import android.widget.EditText
import android.widget.TextView
import java.text.NumberFormat
import java.util.*

fun TextView.currencyFormat() {
    addTextChangedListener(object : TextWatcher {
        override fun afterTextChanged(s: Editable?) {}

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

        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
            removeTextChangedListener(this)
            text = if (s?.toString().isNullOrBlank()) {
                ""
            } else {
                s.toString().currencyFormat()
            }
            if(this@currencyFormat is EditText){
                setSelection(text.toString().length)
            }
            addTextChangedListener(this)
        }
    })
}

fun String.currencyFormat(): String {
    var current = this
    if (current.isEmpty()) current = "0"
    return try {
        if (current.contains('.')) {
            NumberFormat.getNumberInstance(Locale.getDefault()).format(current.replace(",", "").toDouble())
        } else {
            NumberFormat.getNumberInstance(Locale.getDefault()).format(current.replace(",", "").toLong())
        }
    } catch (e: Exception) {
        "0"
    }
}

0

कोटलिन संस्करण:

    var current = ""

    editText.addTextChangedListener(object: TextWatcher {
        override fun afterTextChanged(s: Editable?) {}
        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}

        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
            val stringText = s.toString()

            if(stringText != current) {
                editText.removeTextChangedListener(this)

                val locale: Locale = Locale.UK
                val currency = Currency.getInstance(locale)
                val cleanString = stringText.replace("[${currency.symbol},.]".toRegex(), "")
                val parsed = cleanString.toDouble()
                val formatted = NumberFormat.getCurrencyInstance(locale).format(parsed / 100)

                current = formatted
                editText.setText(formatted)
                editText.setSelection(formatted.length)
                editText.addTextChangedListener(this)
            }
        }
    })

0
public class MoneyEditText extends android.support.v7.widget.AppCompatEditText{
public MoneyEditText(Context context) {
    super(context);
    addTextChangedListener(MoneySplitter());
}
public MoneyEditText(Context context, AttributeSet attrs) {
    super(context, attrs);
    addTextChangedListener(MoneySplitter());
}
public MoneyEditText(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    addTextChangedListener(MoneySplitter());
}
public TextWatcher MoneySplitter() {
    TextWatcher textWatcher = new TextWatcher() {
        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            try
            {
                removeTextChangedListener(this);
                String value = s.toString();
                if (!value.equals(""))
                {
                        if(!TextUtils.isEmpty(value))
                            setText(formatPrice(Double.parseDouble(value)));
                        setSelection(getText().toString().length());

                }
                addTextChangedListener(this);
            }
            catch (Exception ex)
            {
                ex.printStackTrace();
                addTextChangedListener(this);
            }
        }
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        }
        @Override
        public void afterTextChanged(Editable s) {
        }
    };
    return textWatcher;
}

public static String formatPrice(double value){
        int DecimalPointNumber = 2;
        Locale locale = Locale.getDefault();
        DecimalFormat myFormatter = (DecimalFormat) NumberFormat.getCurrencyInstance(locale);
        StringBuilder sb = new StringBuilder();
        if(DecimalPointNumber>0){
            for (int i = 0; i < DecimalPointNumber; i++) {
                sb.append("#");
            }
            myFormatter.applyPattern("###,###."+ sb.toString());
        }else
            myFormatter.applyPattern("###,###"+ sb.toString());

            return Currency.getInstance(Locale.getDefault()).getSymbol() + myFormatter.format(value);
    }
}

और फिर इस ब्लॉक को अपने editText के रूप में उपयोग करें

   <MoneyEditText
   android:id="@+id/txtPrice"
   android:layout_width="match_parent"
   android:layout_height="64dp"
   android:digits="0123456789.,"
   android:inputType="numberDecimal"
   android:selectAllOnFocus="true"
   android:singleLine="true" />

आप इस अनुकूलित संपादन पाठ का उपयोग इनपुट पाठ स्वरूपण के लिए कर सकते हैं जैसा आप चाहते हैं।
— सईद मोहम्मदी

मैंने नकारात्मक संख्याओं को स्वीकार करने के लिए इस वर्ग को बदल दिया। कोड एक उत्तर के रूप में बोल्ड है।
— माइकल फर्नांडिस

0

यह सईद मोहम्मदी जवाब की तरह है लेकिन मैंने नकारात्मक संख्याओं को स्वीकार करना बदल दिया।

  package com.example.liberdade.util
    
    import android.text.Editable
    import android.text.TextWatcher
    import android.widget.EditText
    import java.lang.ref.WeakReference
    import java.math.BigDecimal
    import java.text.NumberFormat
    import java.util.*
    
    
    class MoneyTextWatcher : TextWatcher {
    
    
    
        private val editTextWeakReference: WeakReference<EditText?>?
        private val locale: Locale = Locale("pt", "BR")
        //private final Locale locale;
    
        constructor(editText: EditText?, locale: Locale?) {
            editTextWeakReference = WeakReference<EditText?>(editText)
            //this.locale = if (locale != null) locale else Locale.getDefault()
        }
    
        constructor(editText: EditText?) {
            editTextWeakReference = WeakReference<EditText?>(editText)
            //locale = Locale.getDefault()
        }
    
        override fun beforeTextChanged(
            s: CharSequence?,
            start: Int,
            count: Int,
            after: Int
        ) {
        }
    
        override fun onTextChanged(
            s: CharSequence?,
            start: Int,
            before: Int,
            count: Int
        ) {
        }
    
        override fun afterTextChanged(editable: Editable?) {
            val editText: EditText = editTextWeakReference?.get() ?: return
            editText.removeTextChangedListener(this)
    
            var isNegative = false
            var editableString = editable.toString()
            if (editable != null) {
                if (editableString.contains('-')) {
                    isNegative = true
                    if (editable != null) {
                        editableString = editableString.replace("-","")
                    }
                }
            }
    
            val parsed: BigDecimal? = parseToBigDecimal(editableString, locale)
            //val parsed: BigDecimal? = parseToBigDecimal(editable.toString(), locale)
            var formatted: String = NumberFormat.getCurrencyInstance(locale).format(parsed)
    
            if (isNegative && !(formatted.equals("R\$ 0,00") || formatted.equals("-R\$ 0,00"))) formatted = "-${formatted}"
            editText.setText(formatted)
            editText.setSelection(formatted.length)
            editText.addTextChangedListener(this)
        }
    
        private fun parseToBigDecimal(value: String?, locale: Locale?): BigDecimal? {
            val replaceable = java.lang.String.format(
                "[%s,.\\s]",
                NumberFormat.getCurrencyInstance(locale).currency.symbol
            )
            val cleanString = value!!.replace(replaceable.toRegex(), "")
            return BigDecimal(cleanString).setScale(
                2, BigDecimal.ROUND_FLOOR
            ).divide(
                BigDecimal(100), BigDecimal.ROUND_FLOOR
            )
        }
    }
    
    //como invocar
    //binding.editTextValorCaixa.addTextChangedListener(MoneyTextWatcher(binding.editTextValorCaixa, Locale("pt", "BR")))
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.