今回の目的
EditTextで金額を入力する時、月並みだが、動的に入力した数値をカンマ区切りに変換できないか、
色々調べたところ、ある程度制御が出来るようになったので、紹介していこうと思います。
使用する環境
- AndroidStudio Ver 3.4.1
- Android 10.0 (Q) API 29
TextWatcher
TextWatcher (AndroidDeveloper)
⇨ EditTextの入力を監視するEventListener(編集前の値を取得したり、編集後の値やポジションを取得する等、出来る)
色々詳しいことは、参考サイトや↑のリファレンスを参照してください。
実装に当たって
まずはImplements(実装)していきます。
MainActivity.java
public class SampleClass1 extends AppCompatActivity implements TextWatcher
その後、エラーが出て、「専用のクラスをOverRideせよ」と言われるのでどこかに以下のクラス群を設置します。
MainActivity.java
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
}
とここまでは、調べると色々出てくるので、詳しい内容は参考サイトを見てみてください。
実装
では実際に実装していきます
MainActivity.java
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
//入力直後のテキストを取得
if (!chg_flg){
prevText = charSequence.toString();
}
}
@Override
public void onTextChanged(CharSequence charSequence, int cur, int del, int add) {
try {
if (chg_flg) { return; } //変更途中はスルー
StringBuilder str_claft = new StringBuilder();
String str = charSequence.toString();
//カンマを消そうとしているかチェックする
if (!this.CheckInputCash(prevText, str)) {
//カンマ手前の数字を削除する
cur -= 1;
str_claft.append(str);
str_claft.deleteCharAt(cur);
str = str_claft.toString();
}
//ここでflgを立てておく
//この対策をしておかないと、後々2重で呼び出されることになってめんどくさい。
chg_flg = true;
//ここでカンマを一旦外す。
str = str.replace(",", "");
int kngk = 0;
String tmp_kngk = "";
//現在のカーソル位置を編集用変数に格納。
int sel_pos = cur;
//文字数が3文字以上の場合、カンマ区切りに整形する。
if (str.length() > 3) {
kngk = Integer.parseInt(str);
tmp_kngk = String.format("%,d", kngk);
} else {
//0からスタートの場合は、「0」を削除する。
if (prevText.equals("0")) {
str = str.replace("0", "");
}
tmp_kngk = str;
}
if (cur == 0 && del != 0 && tmp_kngk.length() == 0) {
//削除時、0桁になる場合は「0」をセットする。
tmp_kngk = "0";
sel_pos = 1;
} else {
//追加時、追加後の文字数によってPostionを移動する。
if (del == 0){
if (tmp_kngk.length() == 9 || tmp_kngk.length() == 5) {
// 特定の文字数の時は+2 ex)1,234,567 or 1,234
sel_pos += 2;
} else {
// それ以外は+1
sel_pos += 1;
}
}
}
//範囲以上になる場合は、末尾にPostionをセット。
if (sel_pos > tmp_kngk.length()) {
sel_pos = tmp_kngk.length();
}
//新規と編集でEditTextの参照先が変わる場合は、MODE管理をしておく。
//変わらないであれば、if文自体が要らない。
if (form_mode.equals("00")){
INPUT_KNGK.setText(tmp_kngk);
INPUT_KNGK.setSelection(sel_pos);
}else if(form_mode.equals("01")){
EDIT_KNGK.setText(tmp_kngk);
EDIT_KNGK.setSelection(sel_pos);
}
//終わったら、flgを戻す
chg_flg = false;
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void afterTextChanged(Editable editable) {
try{
if (!chg_flg){return;} //変更途中はスルー
String str = editable.toString();
//ここでチェック機能を走らせることも出来る。
if (str.length() > 11){
MSGFORM1.setVisibility(View.VISIBLE);
ERRMSG1.setVisibility(View.VISIBLE);
ERRMSG1.setText("入力できる桁数を超えています。9桁以内で入力してください。");
}else{
MSGFORM1.setVisibility(View.GONE);
ERRMSG1.setVisibility(View.GONE);
}
} catch (Exception e) {
e.printStackTrace();
}
}
MainActivity.java
/** 削除対象がカンマかどうかチェックする **/
public boolean CheckInputCash(String before,String after){
boolean result = true;
try{
String str_before = before.replace(",","");
String str_after = after.replace(",","");
if (str_before.length() == str_after.length()){
//カンマ外して文字数が一緒ならば、カンマを削除しようとしている
result = false;
}else{
result = true;
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
ポイント
- カンマ区切りに整形する場合、カーソルの持って行き場を指定しないといけないので、そこが大変。
- カーソルがカンマに当たっている状態で削除キーを押すと、後の方にカーソルが当たってしまうので、制御してあげないといけない。
- というより、何が一番大変ってカーソルの位置指定のめんどくささ。
- チェック機能をつけるであれば、「afterTextChanged()」で行う。
- それ以外だと、変な感じの挙動になる。
- EditTextはPrivateで扱えるように定義してあげないといけない。
- 整形後の内容を入れるため。
終わりに
どうでしょうか?
カーソルの扱い方は慣れないと難しいですが、デバッグして引数の値を見ていくと、色々掴めてきます。
他のサイトで見るよりかは簡単に実装できたように感じますが、他に何か参考になりそうなサイトがあれば、ぜひコメントください。
それでは、また。
参考サイト
-
入力を監視するTextWatcher/nyanのアプリ開発
- 個人的にはここのサイトがオススメです。(わかりやすい)
- TextWatcherでリアルタイムに値を取得する方法(Android)