android EditText,键盘textWatcher问题

如何解决android EditText,键盘textWatcher问题

| 我正在开发一个android应用,并且我有一个EditText,用户可以在其中输入数字。我想使用不同的货币格式来格式化数字(例如##,##,###),并且我想即时执行操作,即当用户输入每个数字时(而不是按下Enter时)。我四处搜寻,遇到了TextWatcher,我最初发现它很有前途,但事实证明那是绝对的痛苦。我正在只有软键盘的HTC Desire手机上调试代码。 现在,当用户按下数字(0到9),del(退格)键并按Enter键时,我想获得一个回调。通过测试,我发现了这些(至少在手机上)   1)调用editText onKeyListener   当用户按下del或Enter键时。   当用户按下Enter键时,onKey   一次调用两次功能   (我认为这是针对ACTION_UP和   ACTION_DOWN)。当用户按下del键时,   onKey被调用一次(仅适用于   ACTION_DOWN),我不知道为什么。   用户永远不会调用onKey   按任何数字(0到9),我也   无法理解。      2)TextWatchers 3回调函数   被称为(beforeTextChanged,   onTextChanged,afterTextChanged)   每当用户按下任意数字(0至   9)键。所以我想通过使用   TextWatcher和onKeyListener一起   我可以获得所需的所有回调。 现在我的问题是这些。   1)首先在我的HTC软键盘中   是一个键(带有   向下箭头),当我单击它时   键盘不给而辞职   任何回调。我仍然不敢相信   android让用户编辑字段   并辞职而不让程序   处理(保存)编辑。现在我的   editText显示一个值,而我的   对象具有另一个值(我正在保存   用户在回车时进行编辑,然后回退   通过重置按键盘上的   editText值与   对象,但对此我没有答案   键盘向下键)。      2)其次,我要格式化数字   用户输入新数字后。说   我已经有123个editText和   用户输入了按4,我想要我的   editText显示1,234。我吃饱了   onTextChanged()上的数字和   afterTextChanged()和我可以格式化   数字并将其放回   这些回调中的任何一个中的editText。   我应该使用哪一个?哪一个是   最佳实践?      3)第三个是最关键的   问题。应用启动时,我将   editText中的当前对象值。   假设我在onResume()上放了123,   用户输入一个数字(例如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 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新手,仍然无法相信没有简单的方法可以实时处理textEdit数据(我在iphone上也很轻松地做到了这一点)。谢谢大家 编辑:使用输入过滤器后
InputFilter filter = new InputFilter() { 
    public CharSequence filter(CharSequence source,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   我正在:61234我想要:   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 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文本的末尾,并且当用户按下任意数字时也执行了相同的操作。希望它对某人有帮助。感谢所有尝试提供帮助的人。     ,对于Masked输入,可以将InputFilter子类化 下面是一个示例InputFilter子类,将所有小写字母大写:
   /**
     * This filter will capitalize all the lower case letters that are added
     * through edits.
     */
    public static class AllCaps implements InputFilter {
        public CharSequence filter(CharSequence source,int end,Spanned dest,int dstart,int dend) {
            for (int i = start; i < end; i++) {
                if (Character.isLowerCase(source.charAt(i))) {
                    char[] v = new char[end - start];
                    TextUtils.getChars(source,start,end,v,0);
                    String s = new String(v).toUpperCase();

                    if (source instanceof Spanned) {
                        SpannableString sp = new SpannableString(s);
                        TextUtils.copySpansFrom((Spanned) source,null,sp,0);
                        return sp;
                    } else {
                        return s;
                    }
                }
            }

            return null; // keep original
        }
    }
上面的代码摘自Android的InputFilter实现     ,工作几个小时后,我制作了一个电话输入口罩。 例如,输入\“ 123456 \”后会将其转换为\“ + 1(234)56 \”。从任何位置删除任何符号后,光标将移至正确的位置,而不是开始或结束。 活动中:
    etPhone.addTextChangedListener(new PhoneWatcher(etPhone));
在班上:
private class PhoneWatcher implements TextWatcher {
    private static final String PHONE_MASK = \"+# (###) ###-##-##\";
    private final char[] PHONE_MASK_ARRAY = PHONE_MASK.toCharArray();

    private boolean isInTextChanged;
    private boolean isInAfterTextChanged;
    private EditText editText;
    private int shiftCursor;
    private String text;
    private int cursor;

    public PhoneWatcher(EditText editText) {
        super();
        this.editText = editText;
        isInTextChanged = false;
        isInAfterTextChanged = false;
    }

    @Override
    public synchronized void beforeTextChanged(CharSequence s,int after) {
        shiftCursor = after - count;
    }

    @Override
    public synchronized void onTextChanged(CharSequence s,int count) {
        if (!isInTextChanged) {
            isInTextChanged = true;

            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < s.length(); i++) {
                char symbol = s.charAt(i);
                if (symbol >= \'0\' && symbol <= \'9\')
                    sb.append(symbol);
            }
            String digits = sb.toString();

            sb.setLength(0);
            int j = 0;
            for (int i = 0; i < digits.length(); i++) {
                char digit = digits.charAt(i);
                while (j < PHONE_MASK_ARRAY.length) {
                    if (PHONE_MASK_ARRAY[j] == \'#\') {
                        sb.append(digit);
                        j++;
                        break;
                    } else {
                        sb.append(PHONE_MASK_ARRAY[j]);
                        j++;
                    }
                }
            }

            cursor = editText.getSelectionStart();
            text = sb.toString();

            if (shiftCursor > 0) {
                if (cursor > text.length())
                    cursor = text.length();
                else {
                    while (cursor < PHONE_MASK_ARRAY.length && PHONE_MASK_ARRAY[cursor - 1] != \'#\') {
                        cursor++;
                    }
                }
            } else if (shiftCursor < 0) {
                while (cursor > 0 && PHONE_MASK_ARRAY[cursor - 1] != \'#\') {
                    cursor--;
                }
            }
        }
    }

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

            editText.setText(text);
            editText.setSelection(cursor);

            isInTextChanged = false;
            isInAfterTextChanged = false;
        }
    }
}
    

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?