android EditText,键盘textWatcher问题

Kri*_*dra 14 android formatter textwatcher android-edittext

我正在开发一个Android应用程序,我有一个EditText,用户可以输入数字.我想使用不同的货币格式(比如##,##,###)来格式化数字,我想在运行中进行,即当用户输入每个数字时(而不是按下输入时).我google了一下,遇到了TextWatcher,我首先发现它很有希望,但结果却是一种绝对的痛苦.我正在HTC Desire手机上调试我的代码,它只有一个软键盘.

现在我想在用户按下数字(0到9),del(退格)键并输入密钥时收到回调.从我的测试中我发现了这些(至少在我的手机上)

1)当用户按del或输入键时,将调用editText onKeyListener.当用户按下回车键时,一次输入会调用onKey函数两次(我认为是ACTION_UP和ACTION_DOWN).当用户按下del时,onKey被调用一次(仅适用于ACTION_DOWN),我不知道为什么.用户按下任何数字(0到9)时都不会调用onKey,我也无法理解.

2)每当用户按任意数字(0到9)键时,都会调用TextWatchers 3个回调函数(beforeTextChanged,onTextChanged,afterTextChanged).所以我想通过一起使用TextWatcher和onKeyListener,我可以得到我需要的所有回调.

现在我的问题是这些......

1)首先在我的HTC软键盘上有一个键(带有向下箭头的键盘符号),当我点击它时键盘被重新签名而不给出任何回调.我仍然不能相信Android让用户编辑一个字段并辞职而不让程序处理(保存)编辑.现在我的editText显示一个值,我的对象有另一个值(我在输入时保存用户编辑,并通过使用对象中的值重置editText值来处理键盘按键,但我没有回答此键盘向下键) .

2)其次,我想在用户输入新数字后格式化数字.假设我在editText上已有123并且用户输入了按4,我希望我的editText显示1,234.我得到onTextChanged()和afterTextChanged()的完整数字,我可以格式化数字并将其放回到任何这些回调中的editText.我应该使用哪一个?哪种是最佳做法?

3)第三个是最关键的问题.当应用程序启动时,我将当前对象值放在editText中.假设我把123放在onResume()上,当用户输入一个数字(比如说4)时,我希望它是1234.但是在我的onTextChanged回调中我得到的是4123.当我再按一个键(比如5)我是得到45123.因此对于用户输入,editText光标指向文本的结尾.但是当手动设置值时,editText光标似乎不会更新.我相信我必须在textWatcher回调中做一些事情,但我不知道该怎么办.

我在下面发布我的代码.

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我知道这是一个很大的问题,但我正在研究同样的问题2天.我是Android的新手,仍然不能相信没有简单的方法来处理textEdit数据(我在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}); 
Run Code Online (Sandbox Code Playgroud)

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

myObject.amount = 1234;
ed.setText(amountFormatter.format(myObject.amount).toString());
Run Code Online (Sandbox Code Playgroud)

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

我得到:61234我想要:12346

Kri*_*dra 8

好吧,经过多次敲击后,我找到了解决光标位置问题的工作......我不知道这是不是正确的方法,但我得到了它的工作..

    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;
    }
});
Run Code Online (Sandbox Code Playgroud)

我所做的是对的EDITTEXT的onClick(),我用力把光标在当前的EditText文字的末尾,当用户按下任何数字我也做了相同的.希望它有所帮助.感谢所有试图提供帮助的人.