Flutter自定义输入格式化插件custom_input_formatter的使用

发布于 1周前 作者 eggper 来自 Flutter

Flutter自定义输入格式化插件custom_input_formatter的使用

custom_input_formatter 是一个Flutter插件,提供多种数字格式的高级输入格式化功能,包括金额、电话号码、信用卡号等。该插件支持灵活的分隔符和分组模式配置,能够满足不同场景下的输入格式需求。

2.0.0 版本的重大变更

2.0.0 版本中,插件引入了显著的变化以提高格式化能力和类型安全性。如果你从 1.x 版本升级,请注意以下变更:

构造函数参数变更
  • 旧版本 (1.x):

    CustomNumberInputFormatter(
      rightToLeft: true,
      separator: ' ',
      groupBy: 3,
    )
    
  • 新版本 (2.0.0):

    CustomNumberInputFormatter(
      formatType: FormatType.amount,  // 用于右对齐格式
      separator: ' ',
      groupBy: 3,
    )
    

    rightToLeft 布尔参数已被 formatType 枚举取代,用于指定格式类型。

格式类型规范
  • 旧版本 (1.x):

    // 电话号码格式化
    CustomNumberInputFormatter(
      rightToLeft: false,
      separator: ' ',
      groupBy: 2,
      maxLength: 10,
    )
    
  • 新版本 (2.0.0):

    // 电话号码格式化
    CustomNumberInputFormatter(
      formatType: FormatType.phoneNumber,
      // 其他参数是可选的,因为它们由格式类型预设
    )
    

    现在应使用适当的 FormatType 来配置格式,确保应用程序中的格式一致。

默认值

基于选择的 FormatType,格式特定的配置将自动处理。对于标准格式类型,不再需要指定 groupBymaxLength,这些参数将被忽略。

功能特性

该插件提供了多种数字输入类型的全面格式化支持:

  • 金额格式化(带有千位分隔符)
  • 电话号码格式化(可自定义模式)
  • 信用卡号格式化(4位一组)
  • 社会安全号码格式化
  • 银行账号格式化
  • 日期格式化(DD MM YYYY)
  • 时间格式化(HH MM SS)
  • 邮政编码验证
  • 自定义模式的通用数字格式化

安装

在你的 pubspec.yaml 文件中添加以下依赖:

dependencies:
  custom_input_formatter: ^2.0.0

基本用法

格式类型

CustomNumberInputFormatter 支持多种预定义的格式类型。例如,格式化金额:

TextField(
  inputFormatters: [
    CustomNumberInputFormatter(
      formatType: FormatType.amount,
    ),
  ],
  keyboardType: TextInputType.number,
)

可用的格式类型包括:

  • FormatType.amount:适用于货币金额(如 “1 000 000”)
  • FormatType.phoneNumber:适用于电话号码(如 “07 98 87 66 77”)
  • FormatType.creditCard:适用于信用卡号(如 “4242 4242 4242 4242”)
  • FormatType.socialSecurity:适用于社会安全号码(如 “123-45-6789”)
  • FormatType.bankAccount:适用于银行账号
  • FormatType.date:适用于日期(如 “31 12 2024”)
  • FormatType.time:适用于时间(如 “23 59 59”)
  • FormatType.postalCode:适用于邮政编码
  • FormatType.number:适用于通用数字

高级用法

自定义格式模式

你可以通过指定分隔符和分组大小来创建自定义格式模式:

// 自定义分组模式(如 XX-XXX-XX)
TextField(
  inputFormatters: [
    CustomNumberInputFormatter(
      separator: '-',
      groupBy: 2,
      maxLength: 7,
    ),
  ],
)
银行账号格式化
TextField(
  inputFormatters: [
    CustomNumberInputFormatter(
      formatType: FormatType.bankAccount,
      // 将自动使用模式:XXXX XXXX XXXX XXXX XXXX XXX
    ),
  ],
)
日期输入格式化
TextField(
  inputFormatters: [
    CustomNumberInputFormatter(
      formatType: FormatType.date,
      // 将自动格式化为:DD MM YYYY
    ),
  ],
)

属性

CustomNumberInputFormatter 类接受以下属性:

属性 类型 默认值 描述
separator String ’ ’ 用于分隔各组的字符
groupBy int 3 每组的字符数
maxLength int? null 最大长度(不包括分隔符)
formatType FormatType FormatType.number 应用的格式类型
默认最大长度

每个格式类型都有预定义的最大长度:

  • 信用卡:16位
  • 社会安全号码:9位
  • 邮政编码:5位
  • 日期:8位(DDMMYYYY)
  • 时间:6位(HHMMSS)
格式特定的分组模式

预配置的分组模式适用于特定格式:

  • 信用卡:[4, 4, 4, 4]
  • 社会安全号码:[3, 2, 4]
  • 银行账号:[4, 4, 4, 4, 4, 3]
  • 日期:[2, 2, 4]
  • 时间:[2, 2, 2]

示例

金额格式化
// 输入: "1000000"
// 输出: "1 000 000"
TextField(
  inputFormatters: [
    CustomNumberInputFormatter(
      formatType: FormatType.amount,
    ),
  ],
)
信用卡输入
// 输入: "4242424242424242"
// 输出: "4242 4242 4242 4242"
TextField(
  inputFormatters: [
    CustomNumberInputFormatter(
      formatType: FormatType.creditCard,
    ),
  ],
)
社会安全号码
// 输入: "123456789"
// 输出: "123-45-6789"
TextField(
  inputFormatters: [
    CustomNumberInputFormatter(
      formatType: FormatType.socialSecurity,
    ),
  ],
)

最佳实践

  1. 始终指定适当的键盘类型

    keyboardType: TextInputType.number
    
  2. 考虑与其他格式化器结合使用以进行额外验证

    inputFormatters: [
      FilteringTextInputFormatter.digitsOnly,
      CustomNumberInputFormatter(
        formatType: FormatType.amount,
      ),
    ],
    
  3. 在表单验证逻辑中适当处理空值和无效输入

完整示例 Demo

以下是一个完整的示例,展示了如何在Flutter应用中使用 custom_input_formatter 插件:

import 'package:custom_input_formatter/custom_input_formatter.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Custom Input Formatter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Custom Input Formatter Demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  [@override](/user/override)
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  [@override](/user/override)
  Widget build(BuildContext context) {
    // 金额格式化
    final amountFormatter = CustomNumberInputFormatter(
      formatType: FormatType.amount,
      separator: '.',
      groupBy: 3,
    );

    // 电话号码格式化
    final phoneFormatter = CustomNumberInputFormatter(
      formatType: FormatType.phoneNumber,
      separator: ':',
      groupBy: 2,
      maxLength: 10,
    );

    // 通用数字格式化
    final numberFormatter = CustomNumberInputFormatter(
      formatType: FormatType.number,
      separator: ' ',
      groupBy: 3,
      maxLength: 10,
    );

    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 20.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            // 金额输入框
            TextField(
              inputFormatters: [amountFormatter],
              keyboardType: TextInputType.number,
              decoration: InputDecoration(
                labelText: '金额',
                border: OutlineInputBorder(),
              ),
            ),
            SizedBox(height: 20),
            // 电话号码输入框
            TextField(
              inputFormatters: [phoneFormatter],
              keyboardType: TextInputType.phone,
              decoration: InputDecoration(
                labelText: '电话号码',
                border: OutlineInputBorder(),
              ),
            ),
            SizedBox(height: 20),
            // 通用数字输入框
            TextField(
              inputFormatters: [numberFormatter],
              keyboardType: TextInputType.number,
              decoration: InputDecoration(
                labelText: '通用数字',
                border: OutlineInputBorder(),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

更多关于Flutter自定义输入格式化插件custom_input_formatter的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter自定义输入格式化插件custom_input_formatter的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter中使用custom_input_formatter插件来实现自定义输入格式化的示例代码。

首先,你需要在你的pubspec.yaml文件中添加custom_input_formatter依赖:

dependencies:
  flutter:
    sdk: flutter
  custom_input_formatter: ^x.y.z  # 请将x.y.z替换为最新的版本号

然后,运行flutter pub get来获取依赖。

以下是一个完整的示例代码,展示了如何使用custom_input_formatter插件来格式化输入。例如,我们将实现一个格式化电话号码的输入字段,只允许数字输入,并在输入过程中自动添加空格作为千位分隔符。

import 'package:flutter/material.dart';
import 'package:custom_input_formatter/custom_input_formatter.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Custom Input Formatter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text('Custom Input Formatter Demo'),
        ),
        body: Padding(
          padding: const EdgeInsets.all(16.0),
          child: CustomInputFormatterDemo(),
        ),
      ),
    );
  }
}

class CustomInputFormatterDemo extends StatefulWidget {
  @override
  _CustomInputFormatterDemoState createState() => _CustomInputFormatterDemoState();
}

class _CustomInputFormatterDemoState extends State<CustomInputFormatterDemo> {
  final TextEditingController _controller = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        Text(
          'Formatted Phone Number:',
          style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
        ),
        SizedBox(height: 8),
        TextField(
          controller: _controller,
          decoration: InputDecoration(
            border: OutlineInputBorder(),
            labelText: 'Phone Number',
          ),
          keyboardType: TextInputType.phone,
          inputFormatters: [
            FilteringTextInputFormatter.digitsOnly,  // 只允许数字输入
            CustomTextInputFormatter(
              // 自定义格式化器,在输入过程中添加空格作为千位分隔符
              regex: RegExp(r'(\d{3})(\d{3})(\d{4})'),
              replacement: '$1 $2 $3',
              maxLength: 12,  // 电话号码的最大长度
            ),
          ],
        ),
      ],
    );
  }
}

// 自定义的TextInputFormatter,用于在输入过程中应用正则表达式
class CustomTextInputFormatter extends TextInputFormatter {
  final RegExp regex;
  final String replacement;
  final int maxLength;

  CustomTextInputFormatter({
    required this.regex,
    required this.replacement,
    required this.maxLength,
  });

  @override
  TextEditingValue formatEditUpdate(
    TextEditingValue oldValue,
    TextEditingValue newValue,
  ) {
    if (newValue.text.length > maxLength) {
      return oldValue;  // 防止超过最大长度
    }

    final match = regex.firstMatch(newValue.text);
    if (match != null && match.start == 0 && match.end == newValue.text.length) {
      // 如果整个输入都匹配正则表达式,则不进行格式化
      return newValue;
    } else {
      // 否则,应用替换字符串进行格式化
      return TextEditingValue(
        text: newValue.text.replaceAll(regex, replacement),
        selection: TextSelection.collapsed(offset: newValue.text.length),
      );
    }
  }
}

请注意,上面的代码示例中,CustomTextInputFormatter类是一个自定义的TextInputFormatter,它使用正则表达式来匹配输入,并在匹配失败时应用替换字符串。在这个例子中,正则表达式RegExp(r'(\d{3})(\d{3})(\d{4}))'用于匹配格式为XXX XXX XXXX的电话号码,并在输入过程中自动添加空格作为千位分隔符。

你可以根据需要调整正则表达式和替换字符串来实现不同的输入格式化需求。

回到顶部