LoginSignup
0
0

More than 1 year has passed since last update.

【Android】 TextWatcherを使って、金額入力時にカンマを加える。

Last updated at Posted at 2021-07-23

今回の目的

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で扱えるように定義してあげないといけない。
    • 整形後の内容を入れるため。

終わりに

どうでしょうか?
カーソルの扱い方は慣れないと難しいですが、デバッグして引数の値を見ていくと、色々掴めてきます。

他のサイトで見るよりかは簡単に実装できたように感じますが、他に何か参考になりそうなサイトがあれば、ぜひコメントください。

それでは、また。

参考サイト

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0