私はAndroidアプリに取り組んでおり、ユーザーが数字を入力できるEditTextを持っています。さまざまな通貨形式(たとえば##、##、###)を使用して数値をフォーマットしたいのですが、その場で、つまりユーザーが各桁を入力したとき(Enterキーが押されたときではない)にフォーマットしたいと思います。グーグルで検索して、最初に有望だと思ったTextWatcherに出くわしましたが、それは絶対的な苦痛であることがわかりました。ソフトキーボードしかないHTCDesire電話でコードをデバッグしています。
ここで、ユーザーが数字(0〜9)、del(バックスペース)キーを押してキーを入力したときにコールバックを取得したいと思います。私のテストから、私はこれらを見つけました(少なくとも私の電話で)
1)editText onKeyListenerは、ユーザーがdelまたはEnterキーを押すと呼び出されます。ユーザーがEnterキーを押すと、onKey関数が1回のEnterに対して2回呼び出されます(これはACTION_UPとACTION_DOWNの場合だと思います)。ユーザーがdelを押すと、onKeyが1回呼び出されます(ACTION_DOWNの場合のみ)。理由はわかりません。ユーザーが数字(0から9)を押しても、onKeyが呼び出されることはありませんが、これも理解できません。
2)TextWatchers 3のコールバック関数は、ユーザーが任意の数字(0〜9)キーを押すたびに呼び出されます(beforeTextChanged、onTextChanged、afterTextChanged)。したがって、TextWatcherとonKeyListenerを一緒に使用することで、必要なすべてのコールバックを取得できると思いました。
今私の質問はこれらです。
1)最初に私のHTCソフトキーボードにキー(下向き矢印の付いたキーボード記号)があり、それをクリックすると、キーボードはコールバックを与えずに辞任します。私はまだ、Androidがユーザーにフィールドの編集を許可し、プログラムに編集を処理(保存)させずに辞任させることを信じることができません。これで、editTextに1つの値が表示され、オブジェクトに別の値が表示されます(Enterキーを押したときにユーザーの編集を保存し、editText値をオブジェクトの値にリセットしてキーボードを押し戻す処理を行っていますが、このキーボードのダウンキーに対する回答がありません) 。
2)次に、ユーザーが新しい桁を入力した後に数値をフォーマットしたいと思います。すでにeditTextに123があり、ユーザーが4を押して入力したとすると、editTextに1,234を表示させます。onTextChanged()とafterTextChanged()で完全な数値を取得し、数値をフォーマットして、これらのコールバックのいずれかでeditTextに戻すことができます。どちらを使うべきですか?ベストプラクティスはどれですか?
3)3番目は最も重大な問題です。アプリの起動時に、現在のオブジェクト値をeditTextに入れます。onResume()に123を置き、ユーザーが数字を入力すると(たとえば、4)1234にします。しかし、onTextChangedコールバックでは、取得するのは4123です。もう1つのキー(たとえば、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);
}
}
大きな問題だとは思いますが、同じ問題に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});
アプリが起動すると、editTextに1,234を追加します
myObject.amount = 1234;
ed.setText(amountFormatter.format(myObject.amount).toString());
次に、ユーザーがeditTextをクリックすると、キーボードがポップアップし、ユーザーが数字の6を入力したと言います。
私が得ている:61234私が欲しい:12346