android EditText,键盘textWatcher问题

标签 android android-edittext formatter textwatcher

我正在开发一个 Android 应用程序,我有一个 EditText,用户可以在其中输入数字。我想使用不同的货币格式(例如##、##、###)来格式化数字,并且我想在运行时进行,即当用户输入每个数字时(而不是在按下回车键时)。我用谷歌搜索了一下,找到了 TextWatcher我最初发现它很有希望,但事实证明这绝对是一种痛苦。我在只有软键盘的 HTC Desire 手机上调试我的代码。

现在我想在用户按下数字(0 到 9)、del(退格键)和回车键时得到回调。从我的测试中我发现了这些(至少在我的手机上)

1) editText onKeyListener is called when user presses del or enter key. When user presses enter, onKey function is called twice for one enter (which I believe is for ACTION_UP and ACTION_DOWN). When user presses del, onKey is called once (only for ACTION_DOWN) which I dont know why. onKey is never called when user presses any digits(0 to 9) which too I cant understand.

2) TextWatchers 3 callback functions are called (beforeTextChanged, onTextChanged, afterTextChanged) whenever user presses any number (0 to 9) key . So I thought by using TextWatcher and onKeyListener together I can get all callbacks I need.

现在我的问题是这些..

1) First in my HTC soft keyboard there is a key (a keyboard symbol with a down arrow) and when I click on it keyboard is resigned without giving any callback. I still cant believe android letting user to edit a field and resign without letting program to process (save) the edit. Now my editText is showing one value and my object has another value (I am saving user edits on enter, and handling back press on keyboard by reseting editText value with the value in the object , but I have no answer to this keyboard down key).

2) Second, I want to format the number after user entered the new digit. Say I already have 123 on editText and user entered pressed 4, I want my editText to display 1,234. I get full number on onTextChanged() and afterTextChanged() and I can format the number and put it back to editText in any of these callback. Which one should I use? Which is the best practice?

3) Third one is the most crucial problem. When app start I put the current object value in the editText. Say I put 123 on onResume(), and when user enter a digit (say 4) I want it to be 1234. But on my onTextChanged callback what I am getting is 4123. When I press one more key (say 5) I am getting 45123. So for user inputs editText cursor are pointing to end of the text. But when value is set by hand, editText cursor dont seems to be updating. I believe I have to do something in textWatcher callbacks but I dont know what I should do.

我在下面发布我的代码。

public class AppHome extends AppBaseActivity {
    private EditText ed = null;
    private NumberFormat amountFormatter = null;
    private boolean  isUserInput = true;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.app_home_screen);

        ed = (EditText)findViewById(R.id.main_amount_textfield);
        amountFormatter = new DecimalFormat("##,##,###");


        ed.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                if(event.getAction() == KeyEvent.ACTION_DOWN) 
                    return true;
                String strippedAmount = ed.getText().toString().replace(",", "");
                if(keyCode == KeyEvent.KEYCODE_DEL){
                    //delete pressed, strip number of comas and then delete least significant digit.
                    strippedAmount = strippedAmount.substring(0, strippedAmount.length() - 1);
                    int amountNumeral = 0;
                    try{
                        amountNumeral = Integer.parseInt(strippedAmount);
                    } catch(NumberFormatException e){
                    }
                    myObject.amount = amountNumeral;
                    isUserInput = false;
                    setFormattedAmount(amountNumeral,ed.getId());
                }else if(keyCode == KeyEvent.KEYCODE_ENTER){
                    //enter pressed, save edits and resign keyboard
                    int amountNumeral = 0;
                    try{
                        amountNumeral = Integer.parseInt(strippedAmount);
                    } catch(NumberFormatException e){
                    }
                    myObject.amount = amountNumeral;
                    isUserInput = false;
                    setFormattedAmount(myObject.amount,ed.getId());
                    //save edits
                    save();
                    //resign keyboard..
                    InputMethodManager in = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                    in.hideSoftInputFromWindow(AppHome.this.getCurrentFocus().getWindowToken(),InputMethodManager.HIDE_NOT_ALWAYS);
                }
                return true;
            }
        });

        TextWatcher inputTextWatcher = new TextWatcher() {
            public void afterTextChanged(Editable s) { 
                if(isUserInput == false){
                    //textWatcher is recursive. When editText value is changed from code textWatcher callback gets called. So this variable acts as a flag which tells whether change is user generated or not..Possibly buggy code..:(
                    isUserInput = true;
                    return;
                }
                String strippedAmount = ed.getText().toString().replace(",", "");
                int amountNumeral = 0;
                try{
                    amountNumeral = Integer.parseInt(strippedAmount);
                } catch(NumberFormatException e){
                }
                isUserInput = false;
                setFormattedAmount(amountNumeral,ed.getId());
            }

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

        ed.addTextChangedListener(inputTextWatcher);
    }//end of onCreate...

    public void setFormattedAmount(Integer amount, Integer inputBoxId){
        double amountValue = 0;
        String textString =null;
        TextView amountInputBox = (TextView) findViewById(inputBoxId);

        amountValue = Double.parseDouble(Integer.toString(amount));
        textString = amountFormatter.format(amountValue).toString();
        amountInputBox.setText(textString);
    }
}

我知道这是一个大问题,但我已经为同一个问题工作了 2 天。我是 android 的新手,仍然无法相信没有简单的方法可以即时处理文本编辑数据(我在 iphone 上轻松完成了同样的操作)。谢谢大家

编辑:使用输入过滤器后

InputFilter filter = new InputFilter() { 
    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { 
            String strippedAmount = dest.toString() + source;
            strippedAmount = strippedAmount.replace(",", "");

        int amountNumeral = 0;
        try{
            amountNumeral = Integer.parseInt(strippedAmount);
        } catch(NumberFormatException e){
        }           
            return amountFormatter.format(amountNumeral).toString(); 
    } 
}; 

ed.setFilters(new InputFilter[]{filter}); 

当应用程序启动时,我将 1,234 放在 editText 上

myObject.amount = 1234;
ed.setText(amountFormatter.format(myObject.amount).toString());

然后当用户点击 editText 时,弹出键盘,并说用户输入数字 6

I am getting : 61234 I want : 12346

最佳答案

好吧,经过多次思考,我找到了解决光标位置问题的方法。我不知道这是否是正确的方法,但我成功了。

    TextWatcher inputTextWatcher = new TextWatcher() {
        public void afterTextChanged(Editable s) { 
            if(isUserInput == false){
                //textWatcher is recursive. When editText value is changed from code textWatcher callback gets called. So this variable acts as a flag which tells whether change is user generated or not..Possibly buggy code..:(
                isUserInput = true;
                ed.setSelection(ed.getText().length());
                return;
            }
            String strippedAmount = ed.getText().toString().replace(",", "");
            int amountNumeral = 0;
            try{
                amountNumeral = Integer.parseInt(strippedAmount);
            } catch(NumberFormatException e){
            }
            isUserInput = false;
            setFormattedAmount(amountNumeral,ed.getId());
        }

        public void beforeTextChanged(CharSequence s, int start, int count, int after){
        }
        public void onTextChanged(CharSequence s, int start, int before, int count) {
        }
    };
ed.addTextChangedListener(inputTextWatcher);


ed.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            int length          =   ed.getText().length();
            ed.setCursorVisible(true);
            ed.setSelection(length);
        }
    });

ed.setOnKeyListener(new View.OnKeyListener() {
    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event) {
            if(event.getAction() == KeyEvent.ACTION_UP) 
                return true;
            String strippedAmount = ed.getText().toString().replace(",", "");
            if(keyCode == KeyEvent.KEYCODE_DEL){
                //delete pressed, strip number of comas and then delete least significant digit.
                strippedAmount = strippedAmount.substring(0, strippedAmount.length() - 1);
                int amountNumeral = 0;
                try{
                    amountNumeral = Integer.parseInt(strippedAmount);
                } catch(NumberFormatException e){
                }
                isUserInput = false;
                setFormattedAmount(amountNumeral,ed.getId());
                return true;
            }else if(keyCode == KeyEvent.KEYCODE_ENTER){
                //enter pressed, save edits and resign keyboard
                int amountNumeral = 0;
                try{
                    amountNumeral = Integer.parseInt(strippedAmount);
                } catch(NumberFormatException e){
                }
                isUserInput = false;
                setFormattedAmount(amountNumeral,ed.getId());
                //save edits
                //resign keyboard..
                InputMethodManager in = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                in.hideSoftInputFromWindow(AppHome.this.getCurrentFocus().getWindowToken(),InputMethodManager.HIDE_NOT_ALWAYS);
                return true;
            }
            return false;
    }
});

我所做的是在 editText 的 onClick() 上,我强行将光标放在当前 EditText 文本的末尾,当用户按下任何数字时我也做了同样的事情。希望它对某人有所帮助..感谢所有试图提供帮助的人。

关于android EditText,键盘textWatcher问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5645332/

相关文章:

java - 如何从带有资源的android库项目创建Jar文件?

android - 来自首选项 xml 的 Mailto 可能吗?

android EditText 如何作为 AutoComplete 工作

java - RGB 到 HEX 转换不正确

java - String.format、long 和 DateTime 转换

android - 在android中为我的按钮添加点击效果

android - 设备和 GCM 服务器之间的 Google Cloud Messaging channel 的安全性如何?

Android 自定义 EditText 带有左侧图标,可以更改焦点上的颜色并在编辑文本不为空时保持焦点上的图标颜色?

Python 记录到控制台

charts - Apex 图表工具提示格式化程序 : how to convert number to string