📞

【Flutter】intl_phone_fieldを使って国際化に対応した電話番号入力のテキストフィールドを作成する

2022/11/11に公開約3,400字

概要

複数の国から利用されることを想定して電話番号入力のテキストフィールドを作成した際に、アプリ側で国番号を定義しておいたり、国選択のセレクトボックスを作るのが少し面倒だったため intl_phone_field パッケージを使って実装をしたのですが、intl_phone_fieldを使用した日本語の記事が見つからなかったので備忘録として今回記事に残しました。

intl_phone_fieldとは

https://pub.dev/packages/intl_phone_field

国際電話番号と国番号を入力するためにカスタマイズされたTextFormFieldを提供してくれるパッケージです。

使い方

pubspec.yamlに追記

dependencies:
+ intl_phone_field: ^3.1.0

IntlPhoneFieldを定義する

IntlPhoneField(
  decoration: const InputDecoration( // TextFieldの見た目を整える
    labelText: 'Phone Number',
    border: OutlineInputBorder(
        borderSide: BorderSide(),
    ),
  ),
  initialCountryCode: 'JP', // 最初に表示する国を指定
  onCountryChanged: (country) { // 国を変更したときに発火
    print(country)
  }

  onChanged: (phone) { // 番号の入力・削除で発火
    print(phone);
  },
  
  // バリデーションメッセージを設定
  // 指定しなかった場合、デフォルトでは'Invalid Mobile Number'が表示される
  invalidNumberMessage: '正しい電話番号を入力してください',
)

他にも色々なプロパティが指定できるため、色々なカスタマイズができそうでした!
onCountryChangedとonChangedで取得できるデータは下記になります。

  • onCountryChangedで取得できるデータ
Country(
  name: 'Japan',  // 国名
  flag: '🇯🇵',     // 国旗アイコン
  code: 'JP',     // 国名コード
  dialCode: '81', // ダイアルコード
  minLength: 10,  // 最小桁数
  maxLength: 10,  // 最大桁数
);
  • onChangedで取得できるデータ
PhoneNumber(
  countryISOCode: 'JP',           // ISO国名コード
  countryCode: '+81',             // 国番号
  number: '9012345678',           // 実際に入力した番号
  completeNumber: '+819012345678' // 国番号 + 入力した番号
);

「国番号 + 電話番号」で取得する方法

「国番号 + ユーザーの電話番号」を取得したい場合に、TextEditingControllerで定義したcontrollerからは取得できないため、暫定的に下記方法で対応しました。

  • onChangedで入力がある度にcompleteNumberをStateとして保持しておく

または

  • onCountryChangedで国を変更する度にStateとして国番号を保持し、
    送信ボタン押下時の処理で「Stateとして保持している国番号 + 入力値」を作成する

カスタマイズしてみる

簡単なカスタマイズとして日本を選択した場合のみ、labelTextとinvalidNumberMessageが日本語で表示されるようにしました。

  1. initialCountryCodeに「JP」を指定する
  2. 選択中の国を保持するStateを定義する
    デフォルト値には「Japan」を指定しておく
  3. onCountryChanged内で国が変更される度にStateを変更する
  4. labelTextとinvalidNumberMessageに文言を設定する
class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);
  
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  // 2
+ String selectedCountryName = 'Japan';

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('電話番号入力'),
      ),
      body: IntlPhoneField(
        decoration: InputDecoration(

          // 4
+         labelText:
+             selectedCountryName == 'Japan' ? '電話番号' : 'Phone Number',
          border: const OutlineInputBorder(
            borderSide: BorderSide(),
          ),
        ),
        onCountryChanged: (country) {
          // 3
          setState(() {
            selectedCountryName = country.name;
          });
        },
        
        // 1
+       initialCountryCode: 'JP',

        // 4
+       invalidNumberMessage: selectedCountryName == 'JP'
+           ? '正しい電話番号を入力してください'
+           : 'Invalid Mobile Number',
      ),
    );
  }
}

最後に

似たようなパッケージでextended_phone_number_inputというパッケージもあり、こちらも様々なカスタマイズができそうでした!
LIKE数が多かったため今回はintl_phone_fieldを使用しましたが、IntlPhoneFieldを呼ぶだけでとても簡単に実装ができましたので電話番号入力のテキストフィールドを作成する際にはぜひ参考にしてみてください!

GitHubで編集を提案

Discussion

ログインするとコメントできます