Я работаю над Android-приложением, и у меня есть EditText, где пользователь может вводить числа. Я хочу отформатировать номер, используя разные форматы валют (например, ##, ##, ###), и я хочу сделать это "на лету", т.е. когда пользователь вводит каждую цифру (а не при нажатии на ввод). Я googled вокруг, и наткнулся TextWatcher, который я впервые нашел многообещающим, но это оказалось абсолютной болью. Я отлаживаю свой код на телефоне HTC Desire, который имеет только мягкую клавиатуру.
Теперь я хочу получить обратный вызов, когда пользователь нажимает цифры (от 0 до 9), del (backspace) и вводит ключ. Из моего тестирования я нашел их (по крайней мере, на моем телефоне)
1) editText onKeyListener вызывается когда пользователь нажимает del или вводит ключ. Когда пользователь нажимает 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 там является ключом (символ клавиатуры с стрелка вниз), и когда я нажимаю на нее клавиатура ушла в отставку, не давая любой обратный вызов. Я все еще не верю андроид, позволяющий пользователю редактировать поле и уйти в отставку, не позволяя программе обработать (сохранить) редактирование. Теперь мой editText показывает одно значение, а мое объект имеет другое значение (я сохраняю редактирование пользователя при вводе и обратная обработка нажмите на клавиатуру, перейдя по ссылке Значение editText со значением в объект, но у меня нет ответа на этот вопрос клавиатура вниз).
2) Во-вторых, я хочу отформатировать номер после ввода пользователем новой цифры. Сказать У меня уже есть 123 на editText и введенный пользователем 4, я хочу, чтобы editText для отображения 1,234. Я получаю полный число на onTextChanged() и afterTextChanged() и я могу форматировать номер и вернуть его обратно editText в любом из этих обратных вызовов. Какой из них я должен использовать? Какой лучшая практика?
3) Третий - самый важный проблема. Когда приложение запускается, я текущее значение объекта в editText. Скажем, я положил 123 на onResume(), и когда пользователь вводит цифру (скажем, 4) Я хочу должно быть 1234. Но на моем onTextChanged обратный вызов, что я получаю, - 4123. Когда Я нажимаю еще один ключ (скажем, 5) Я получив 45123. Таким образом, для пользовательских входов Курсор editText указывает на конец текст. Но когда значение задается hand, editText cursor dont, кажется, обновление. Я считаю, что мне нужно сделать что-то в обратных вызовах 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);
}
}
Я знаю, что это большой вопрос, но я работаю над этой же проблемой в течение 2 дней. Я новичок в андроиде и все еще не могу поверить, что нет простого способа обрабатывать данные TextEdit на лету (я делал то же самое на iphone с легкостью). Спасибо всем
EDIT: после использования входного фильтра
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
Я получаю: 61234 Я хочу: 12346