简体   繁体   English

如何实现实时EditText格式?

[英]How to implement real time EditText formatting?

I want to have EditText that automatically formats user input in real time, for example, it converts 1000000 to 1,000,000 我想要具有自动自动实时格式化用户输入格式的EditText ,例如,它将1000000转换为1,000,000

I tried Android Money Input with fixed decimal but when I set the text, the app crashes 我尝试使用固定的十进制数输入Android Money,但是当我设置文本时,应用崩溃

EditText etMoney;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    etMoney = (EditText)findViewById(R.id.etMoney);
    etMoney.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            etMoney.setText(currencyFormat(etMoney.getText().toString()));
        }

        @Override
        public void afterTextChanged(Editable editable) {
        }
    });
}
public static String currencyFormat(String amount) {
    DecimalFormat formatter = new DecimalFormat("###,###,###");
    return formatter.format(Double.parseDouble(amount));
}

The output I want is a real-time converter directly into the EditText but as soon as I type something in EditText the app crashes. 我想要的输出是直接转换为EditText的实时转换器,但是一旦我在EditText键入内容,应用就会崩溃。

Crash Log: 崩溃日志:

06-20 15:19:57.453 1699-1715/system_process E/ActivityManager: ANR in com.hassilproject.myapplication (com.hassilproject.myapplication/.MainActivity)
                                                               PID: 2521
                                                               Reason: Input dispatching timed out (Waiting to send key event because the focused window has not finished processing all of the input events that were previously delivered to it.  Outbound queue length: 0.  Wait queue length: 1.)

change this code 更改此代码

 etMoney.addTextChangedListener(new TextWatcher() {
    @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) {
        etMoney.setText(currencyFormat(editable.toString()));
    }
});

Try this, I created a custom view to input currency. 试试这个,我创建了一个自定义视图来输入货币。 Use currency() method to get value in EditText. 使用currency()方法获取EditText中的值。

class CurrencyInput(context: Context, attributeSet: AttributeSet) : TextInputEditText(context, attributeSet) {

    private val currencyTextWatcher = CurrencyWatcher()

    override fun onFocusChanged(focused: Boolean, direction: Int, previouslyFocusedRect: Rect?) {
        super.onFocusChanged(focused, direction, previouslyFocusedRect)
        if (focused) addTextChangedListener(currencyTextWatcher) else removeTextChangedListener(currencyTextWatcher)
    }

    fun currency(): Long = currencyTextWatcher.amount
    private fun Long.toDecimalStr(): String = decimalFormatter().format(this)

    inner class CurrencyWatcher : TextWatcher {
        var amount = 0L
        var amountDecimal = ""
        override fun afterTextChanged(editable: Editable?) {
            editable?.toString()?.run {
                when {
                    equals("") -> {
                        amount = 0
                        amountDecimal = "0"
                    }
                    else -> {
                        amount = replace(",", "").replace(".", "").toLong()
                        amountDecimal = if (amount >= 1000) amount.toDecimalStr() else amount.toString()
                    }
                }
                this@CurrencyInput.apply {
                    removeTextChangedListener(this@CurrencyWatcher)
                    amount.let {
                        setText(amountDecimal)
                        setSelection(amountDecimal.length)
                    }
                    addTextChangedListener(this@CurrencyWatcher)
                }
            }
        }
        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { }
        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { }
    }

}

Replace with your package name when using CurrencyInput in your layout 在布局中使用CurrencyInput时,用包名称替换

<com.google.android.material.textfield.TextInputLayout
            style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="7dp"
            android:hint="Currency"
            app:endIconMode="clear_text">
            <com.package.CurrencyInput
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:inputType="number"/>
        </com.google.android.material.textfield.TextInputLayout>

I hope this will work for you. 希望这对您有用。

 etMoney.addTextChangedListener(new TextWatcher() {
            @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) {
                etMoney.removeTextChangedListener(this);
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            if (!editable.toString().equalsIgnoreCase("")) {
                                etMoney.setText("" + currencyFormat(editable.toString()));
                            }
                        } catch (NumberFormatException e) {
                            e.printStackTrace();
                        }
                    }
                }, 4000); //after 4 second it will update to UI.
               etMoney.addTextChangedListener(this);
            }
        });

Currency Format method given below 货币格式方法如下

 public String currencyFormat(String amount) {
        return new DecimalFormat("###,###,###").format(Double.parseDouble(amount));
    }

//Create Method //创建方法

private TextWatcher onTextChangedListener() {
        return 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) {
                editText.removeTextChangedListener(this);

                try {
                    String originalString = s.toString();

                    Long longval;
                    if (originalString.contains(",")) {
                        originalString = originalString.replaceAll(",", "");
                    }
                    longval = Long.parseLong(originalString);

                    DecimalFormat formatter = (DecimalFormat) NumberFormat.getInstance(Locale.US);
                    formatter.applyPattern("#,###,###,###");
                    String formattedString = formatter.format(longval);

                    //setting text after format to EditText
                    editText.setText(formattedString);
                    editText.setSelection(editText.getText().length());
                } catch (NumberFormatException nfe) {
                    nfe.printStackTrace();
                }

                editText.addTextChangedListener(this);
            }
        };
    }

//Call method //调用方法

editText.addTextChangedListener(onTextChangedListener());

Every time you change the text of EditText, the TextWatcher method will get called. 每次更改EditText的文本时,都会调用TextWatcher方法。 So you must set flag to indicate that change source. 因此,您必须设置标志以指示更改源。 And the TextWatcher callback method. 还有TextWatcher回调方法。 check indicating flag to avoid infinite loop. 检查指示标志以避免无限循环。

etMoney.addTextChangedListener(new TextWatcher() {
    private boolean changedByFormatText = false;
    @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) {
        if(changedByFormatText) {
            changedByFormatText = false;
            return;
        } else {
           changedByFormatText = true;
           etMoney.setText(currencyFormat(etMoney.getText().toString()));
        }

    }
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM