LoginSignup
0
0

【Flutter】TextFieldで3桁区切り整数6桁小数点第一まで入力できるようにする

Posted at

結論から書くとこれ

class DecimalTextInputFormatter extends TextInputFormatter {
  @override
  TextEditingValue formatEditUpdate(
      TextEditingValue oldValue, TextEditingValue newValue) {
    // ユーザーが新しいテキストを入力したときの処理

    // テキストからカンマを除去
    final unformatted = newValue.text.replaceAll(',', '');

    // テキストが空の場合、最初の文字を削除できるようにする
    if (unformatted.isEmpty) {
      return TextEditingValue(
        text: '',
        selection: TextSelection.collapsed(offset: 0),
      );
    }

    // 正規表現を使用して整数部と小数部を確認
    final regExp = RegExp(r'^\d{0,6}(\.\d{0,1})?$');
    if (regExp.hasMatch(unformatted)) {
      // カンマを除去
      final parts = unformatted.split('.');
      String integerPart = parts[0];
      String decimalPart = parts.length > 1 ? '.' + parts[1] : '';

      // 整数部を3桁ごとにカンマで区切る
      integerPart = _formatWithCommas(integerPart);

      // 新しいテキストを整形
      String formattedValue = integerPart + decimalPart;

      // 新しいテキストが".0"で終わる場合、それを削除
      if (formattedValue.endsWith('.0')) {
        formattedValue = formattedValue.substring(0, formattedValue.length - 2);
      }

      return TextEditingValue(
        text: formattedValue,
        selection: TextSelection.collapsed(offset: formattedValue.length),
      );
    }

    // 条件を満たさない場合、変更を受け入れず、元のテキストを維持
    return oldValue;
  }

  String _formatWithCommas(String value) {
    // 整数部を3桁ごとにカンマで区切る
    if (value.length <= 3) {
      return value;
    }

    final integerPart = value.substring(0, value.length - 3);
    final decimalPart = value.substring(value.length - 3);

    return _formatWithCommas(integerPart) + ',' + decimalPart;
  }
}

TextField部分

Container(
  width: 180,
  height: 45,
  decoration: BoxDecoration(
    color: Colors.grey.withOpacity(0.1),
    borderRadius: BorderRadius.circular(5),
  ),

  child: Padding(
    padding: const EdgeInsets.symmetric(vertical: 7),
    child: TextField(
        style: const TextStyle(
          fontSize: 16,
          color: Colors.black, // 黒色に設定
        ),
        controller: controller,
        decoration: const InputDecoration(
          filled: true,
          fillColor: Colors.transparent,
          border: InputBorder.none,
        ),
        keyboardType: const TextInputType.numberWithOptions(decimal: true),
        inputFormatters: [DecimalTextInputFormatter()],
        onChanged: widget.onChanged),
  ),
),

init部分

  @override
  void initState() {
    super.initState();

    controller = TextEditingController.fromValue(
      DecimalTextInputFormatter().formatEditUpdate(
        TextEditingValue.empty,
        TextEditingValue(text: widget.value),
      ),
    );
  }

dispose部分

  @override
  void dispose() {
    controller.dispose(); // Dispose the TextEditingController
    super.dispose();
  }

ちなみにChatgptに使ったメモはこれ

整数は6桁まで入力可能
小数点は第一まで入力可能
3桁区切りを追加
4桁以上入力できないプログラムは作成するな
カンマが二つつかないようにしろ
999,999.0のような文字が桁が含まれていても消せるようにしろ
最初の文字も必ず削除できるようにしろ
3桁区切りがちゃんと動作するようにしろ
新しく入力されるときに最後が.0の場合はそれを消すようにして

まとめ

整数で3桁区切りをするって内容はあったけど、小数点込みで情報を探して見つからなくて途方に暮れてたんですが、ネットの情報探せなかったからもうヤケクソでChatgptに必要な内容をメモに追加しつつ問題点を書き込んでひたすら実装させたらそれっぽい動作する感じに動いたので情報共有も兼ねて投稿です。

多分同じとこでつまづく人がいるかなって思ったんでそんな方達の参考になれば幸いです。

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