如何实现实时EditText格式?

时间:2019-06-20 03:35:32

标签: java android android-edittext

我想使用EditText自动实时格式化用户输入的内容,例如,它将1000000转换为1,000,000

我尝试了Android Money Input with fixed decimal,但是在设置文字时,应用崩溃了

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

我想要的输出是直接转换为EditText的实时转换器,但是一旦我在EditText中键入内容,应用就会崩溃。

崩溃日志:

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.)

5 个答案:

答案 0 :(得分:0)

更改此代码

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

答案 1 :(得分:0)

尝试一下,我创建了一个自定义视图来输入货币。使用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) { }
    }

}

在布局中使用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>

答案 2 :(得分:0)

我希望这对您有用。

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

下面给出的货币格式方法

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

答案 3 :(得分:0)

//创建方法

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

//调用方法

editText.addTextChangedListener(onTextChangedListener());

答案 4 :(得分:0)

每次更改EditText的文本时,都会调用TextWatcher方法。因此,您必须设置标志以指示更改源。还有TextWatcher回调方法。检查指示标志以避免无限循环。

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

    }
});