Flutter表单构建插件fl_form的使用

Flutter表单构建插件fl_form的使用

特性

此包为您的应用程序提供了一些数据类型的表单字段,它可以与您应用中的表单一起工作。

  • 文本输入
  • 头像
  • 日期、时间、持续时间
  • 单项选择器
  • 多项选择器
  • 布尔值
  • 单选按钮
  • 复选框组

使用

需要主题扩展

表单字段要求应用程序使用主题扩展: FlFormFieldTheme

配置

MaterialApp(
    title: 'Flutter Demo',
    theme: ThemeData.dark(
    useMaterial3: true,
    ).copyWith(extensions: [
    FlFormFieldTheme.dark(context),
    ]),
    home: const MainExample(),
);

FlFormFieldTheme

...
  final TextStyle labelStyle;
  final InputDecorationTheme inputDecorationTheme;
  final TextStyle style;
  final TextStyle errorStyle;
  final TextStyle placeHolderStyle;

  FlFormFieldTheme({
    required this.labelStyle,
    required this.inputDecorationTheme,
    required this.style,
    required this.errorStyle,
    required this.placeHolderStyle,
  });

1. FlTextFormField

示例:简单文本

FlTextFormField(
    label: 'Email',
    isRequired: true,
    autovalidateMode: AutovalidateMode.always,
    validator: (value) {
        return 'Email invalid';
    },
    placeholderText: 'Type your email',
),

示例:密码文本

FlTextFormField(
    prefixIcon: const Icon(Icons.lock),
    label: 'Password',
    placeholderText: '* * * * * *',
    isRequired: true,
    isPassword: true,
),

示例:区域文本

FlTextFormField(
    maxLines: 4,
    label: 'Description',
    autovalidateMode: AutovalidateMode.always,
    placeholderText: 'Type your description',
    validator: (value) {
        return 'Description invalid';
    },
),

FlDateFormField

FlDateFormField(
    autovalidateMode: AutovalidateMode.always,
    prefixIcon: const Icon(Icons.date_range),
    firstDate: DateTime.now(),
    lastDate: DateTime.now().add(const Duration(days: 100)),
    label: 'Date of birth',
    placeholderText: 'dd/MM/yyyy',
    validator: (value) {
        return 'Date invalid';
    },
),

FlTimeFormField

FlTimeFormField(
    label: 'Time Start',
    placeholderText: 'HH:MM',
    autovalidateMode: AutovalidateMode.always,
    validator: (value) {
        return 'Time invalid';
    },
    prefixIcon: Icon(Icons.alarm),
),

FlDateAndTimeFormField

FlDateAndTimeFormField(
    firstDate: DateTime.now(),
    lastDate: DateTime.now().add(const Duration(days: 100)),
    label: 'Date of birth',
    placeholderText: 'dd/MM/yyyy',
    autovalidateMode: AutovalidateMode.always,
    validator: (value) => 'Date invalid',
),

FlDurationFormField

FlDurationFormField(
    prefixIcon: Icon(Icons.date_range),
    label: 'Select Duration',
    placeholderText: 'hh : mm',
),

AvatarFormFieldPage

1. 默认头像表单字段

FlAvatarFormField(
    radius: 64,
    autovalidateMode: AutovalidateMode.always,
    validator: (value) {
        if (value == null) {
            return 'Need update your avatar';
        }
    },
),

2. 自定义头像表单字段

Center(
    child: FlRawAvatarFormField(
        builder: (
            {required context, data, required didChange, error}) {
        if (data == null) {
            return GestureDetector(
            onTap: () {
                FlRawAvatarFormField.pickFile().then((value) {
                if (value != null) {
                    didChange(value);
                }
                });
            },
            child: Container(
                height: 80,
                width: 80,
                decoration: BoxDecoration(
                color: Colors.grey,
                borderRadius: BorderRadius.circular(12),
                ),
            ),
            );
        } else {
            if (data.file != null) {
            return Container(
                height: 80,
                width: 80,
                decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(12),
                    image: DecorationImage(
                        fit: BoxFit.cover,
                        image: FileImage(data.file!))),
            );
            } else {
            return Container(
                height: 80,
                width: 80,
                decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(12),
                    image: DecorationImage(
                        fit: BoxFit.cover,
                        image: NetworkImage(data.link!))),
            );
            }
        }
        },
    ),
),

Bool Value FormField

1. FlBoolFormField

FlBoolFormField(
    spacing: 16,
    title: 'Select All',
)

2. FlRawBoolFormField

FlRawBoolFormField(
    title: 'Select All',
    rawBuilder: (context, data, didChange) {
    return Container(
        padding: const EdgeInsets.symmetric(vertical: 12),
        child: Row(
        children: [
            Checkbox(
            value: data ?? false,
            onChanged: (value) {
                didChange(value);
            },
            ),
            const Expanded(
            child: Text('Select All'),
            )
        ],
        ),
    );
    },
),

Single Item Picker Form Field

SingleItemPickerFormField<SimpleData>(
    label: 'Select Item customize',
    placeholderText: 'Select Item',
    itemListBuilder: (context, data, isSelected) {
    return Container(
        padding: const EdgeInsets.symmetric(
        vertical: 12,
        horizontal: 16,
        ),
        child: Row(
        children: [
            const CircleAvatar(
            radius: 24,
            ),
            const SizedBox(
            width: 12,
            ),
            Expanded(
                child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
                Text(
                data.title,
                style: Theme.of(context).textTheme.bodyMedium,
                ),
                const SizedBox(
                height: 2,
                ),
                Text(
                data.subTitle,
                style: Theme.of(context).textTheme.labelMedium,
                ),
            ],
            )),
            if (isSelected) const Icon(Icons.done)
        ],
        ),
    );
    },
    contentSelectedBuilder: (data, context) => Container(
    child: Row(
        children: [
        const CircleAvatar(
            radius: 16,
        ),
        const SizedBox(
            width: 12,
        ),
        Expanded(
            child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
            Text(
                data.title,
                style: Theme.of(context).textTheme.bodyMedium,
            ),
            const SizedBox(
                height: 2,
            ),
            Text(
                data.subTitle,
                style: Theme.of(context).textTheme.labelMedium,
            ),
            ],
        ))
        ],
    ),
    ),
    options: [
    SimpleData(title: 'Title 1', subTitle: 'Sub title 1'),
    SimpleData(title: 'Title 2', subTitle: 'Sub title 2'),
    SimpleData(title: 'Title 3', subTitle: 'Sub title 3'),
    SimpleData(title: 'Title 4', subTitle: 'Sub title 4'),
    SimpleData(title: 'Title 5', subTitle: 'Sub title 5'),
    SimpleData(title: 'Title 6', subTitle: 'Sub title 6'),
    SimpleData(title: 'Title 7', subTitle: 'Sub title 7'),
    SimpleData(title: 'Title 8', subTitle: 'Sub title 8'),
    ],
)

Multiple Item Picker Form Field

MultipleItemPickerFormField<SimpleData>(
    label: 'Select Items customize',
    placeholderText: 'Select Items',
    autovalidateMode: AutovalidateMode.always,
    validator: (value) {
    return 'Data Invalid';
    },
    itemListBuilder: (context, data, isSelected) {
    return Container(
        padding: const EdgeInsets.symmetric(
        vertical: 12,
        horizontal: 16,
        ),
        child: Row(
        children: [
            const CircleAvatar(
            radius: 24,
            ),
            const SizedBox(
            width: 12,
            ),
            Expanded(
                child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
                Text(
                data.title,
                style: Theme.of(context).textTheme.bodyMedium,
                ),
                const SizedBox(
                height: 2,
                ),
                Text(
                data.subTitle,
                style: Theme.of(context).textTheme.labelMedium,
                ),
            ],
            )),
            if (isSelected) const Icon(Icons.done)
        ],
        ),
    );
    },
    contentSelectedBuilder: (data, context) => Container(
    child: Wrap(
        spacing: 8,
        children: [
        ...data
                ?.map((e) => Chip(
                        label: Text(e.title),
                    ))
                .toList() ??
            []
        ],
    ),
    ),
    options: [
    SimpleData(title: 'Title 1', subTitle: 'Sub title 1'),
    SimpleData(title: 'Title 2', subTitle: 'Sub title 2'),
    SimpleData(title: 'Title 3', subTitle: 'Sub title 3'),
    SimpleData(title: 'Title 4', subTitle: 'Sub title 4'),
    SimpleData(title: 'Title 5', subTitle: 'Sub title 5'),
    SimpleData(title: 'Title 6', subTitle: 'Sub title 6'),
    SimpleData(title: 'Title 7', subTitle: 'Sub title 7'),
    SimpleData(title: 'Title 8', subTitle: 'Sub title 8'),
    ],
)

Radio Button Group FormField

FlRadioButtonFormField(
    isRequired: true,
    autovalidateMode: AutovalidateMode.always,
    validator: (value) {
    if (value == null) return 'Data invalid';
    return null;
    },
    label: 'Select Item',
    options: const [
    'Option 1',
    'Option 2',
    'Option 3',
    ],
)

Checbox Group FormField

FlCheckboxGroupFormField(
    isRequired: true,
    autovalidateMode: AutovalidateMode.always,
    validator: (value) {
    if (value == null || value.isEmpty) return 'Data invalid';
    return null;
    },
    label: 'Select Item',
    options: const [
    'Item 1',
    'Item 2',
    'Item 3',
    'Item 4',
    'Item 5',
    'Item 6',
    ],
)

更多关于Flutter表单构建插件fl_form的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter表单构建插件fl_form的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中,fl_form 是一个用于构建和管理表单的插件,它提供了丰富的功能和灵活的API来简化表单开发。以下是一个使用 fl_form 构建简单表单的代码示例,展示了如何创建表单、添加字段、以及处理表单提交。

首先,确保你已经在 pubspec.yaml 文件中添加了 fl_form 依赖:

dependencies:
  flutter:
    sdk: flutter
  fl_form: ^最新版本号  # 请替换为最新的版本号

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

接下来,创建一个简单的 Flutter 应用,并使用 fl_form 来构建表单。以下是一个完整的示例代码:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final _formKey = GlobalKey<FormState>();
  late FlFormController _formController;

  @override
  void initState() {
    super.initState();
    _formController = FlFormController(
      fields: [
        FlFormField(
          name: 'name',
          title: 'Name',
          validators: [FlValidators.required()],
          widget: TextFormField(
            decoration: InputDecoration(border: OutlineInputBorder()),
          ),
        ),
        FlFormField(
          name: 'email',
          title: 'Email',
          validators: [
            FlValidators.required(),
            FlValidators.email(),
          ],
          widget: TextFormField(
            decoration: InputDecoration(border: OutlineInputBorder()),
            keyboardType: TextInputType.emailAddress,
          ),
        ),
        FlFormField(
          name: 'password',
          title: 'Password',
          validators: [FlValidators.required()],
          widget: TextFormField(
            decoration: InputDecoration(border: OutlineInputBorder()),
            obscureText: true,
          ),
        ),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Form Example'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Form(
          key: _formKey,
          child: Column(
            children: [
              Expanded(
                child: FlForm(
                  formController: _formController,
                ),
              ),
              SizedBox(height: 20),
              ElevatedButton(
                onPressed: () async {
                  if (_formKey.currentState!.validate()) {
                    final formValues = await _formController.save();
                    print('Form Submitted: $formValues');
                    // 你可以在这里处理表单提交逻辑,比如发送到服务器
                  }
                },
                child: Text('Submit'),
              ),
            ],
          ),
        ),
      ),
    );
  }

  @override
  void dispose() {
    _formController.dispose();
    super.dispose();
  }
}

在这个示例中:

  1. 我们创建了一个 FlFormController 实例来管理表单字段。
  2. 每个字段都通过 FlFormField 定义,包括字段名、标题、验证器和对应的 TextFormField 小部件。
  3. 使用 Form 小部件包裹 FlForm,并设置一个 GlobalKey 来验证表单。
  4. 在提交按钮的 onPressed 回调中,我们首先验证表单,如果验证通过,则调用 _formController.save() 方法来获取表单字段的值。

这个示例展示了如何使用 fl_form 插件来简化表单的构建和管理。你可以根据需要添加更多的字段和验证规则,以及处理表单提交的逻辑。

回到顶部