Flutter 表单

表单 -- Switch

Switch
  value:开关的值,一般与状态字段绑定
  onChanged:开关状态变更时调用
  activeColor:开关开启时的圆圈颜色
  activeTrackColor:开关开启时的轨道颜色
  inactiveThumbColor:开关关闭时的圆圈颜色
  inactiveTrackColor:开关关闭时的轨道颜色

CupertinoSwitch(iOS 风格的开关)
  import 'package:flutter/cupertino.dart';
 
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';

class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Switch'),
      ),
      body: const SwitchDemo(),
    );
  }
}

class SwitchDemo extends StatefulWidget {
  const SwitchDemo({Key? key}) : super(key: key);

  @override
  State<SwitchDemo> createState() => _SwitchDemoState();
}

class _SwitchDemoState extends State<SwitchDemo> {
  // Switch开关的选中状态
  bool _switchValue = false;

  @override
  Widget build(BuildContext context) {
    return ListView(
      children: [
        // Switch 简单用法
        ListTile(
          leading: Switch(
            value: _switchValue,
            onChanged: (bool value) {
              setState(() {
                _switchValue = value;
              });
            },
          ),
          title: Text('基本用法:${_switchValue == true ? '选中' : '未选中'}'),
        ),
        // Switch 属性介绍
        ListTile(
          leading: Switch(
            value: _switchValue,
            onChanged: (bool value) {
              setState(() {
                _switchValue = value;
              });
            },
            // 开关打开时圆圈的颜色
            activeColor: Colors.green,
            // 开关打开时轨道的颜色
            activeTrackColor: Colors.green[100],
            // 开关关闭时圆圈的颜色
            inactiveThumbColor: Colors.yellow,
            // 开关关闭时轨道的颜色
            inactiveTrackColor: Colors.yellow[100],
          ),
          title: Text('修改属性:${_switchValue == true ? '选中' : '未选中'}'),
        ),
        // iOS 风格的开关
        ListTile(
          leading: CupertinoSwitch(
            value: _switchValue,
            onChanged: (bool value) {
              setState(() {
                _switchValue = value;
              });
            },
            // 开关圆圈的颜色
            thumbColor: Colors.red,
            // 开关打开时轨道的颜色
            activeColor: Colors.red[100],
            // 开关关闭时轨道的颜色
            trackColor: Colors.yellow,
          ),
          title: Text('iOS 风格的开关:${_switchValue == true ? '选中' : '未选中'}'),
        ),
      ],
    );
  }
}

 

表单 -- Checkbox

Checkbox
  value:复选框的值,取值共3个:true, false, null(tristate 取值为 true 时)
  onChanged:复选框状态更改时调用
  activeColor:选中时,复选框背景的颜色
  checkColor:选中时,复选框中对号的颜色

CheckboxListTile
  title:标题
  subtitle:子标题
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart' show timeDilation;

class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Checkbox Demo'),
      ),
      body: const CheckboxDemo(),
    );
  }
}

class CheckboxDemo extends StatefulWidget {
  const CheckboxDemo({Key? key}) : super(key: key);

  @override
  State<CheckboxDemo> createState() => _CheckboxDemoState();
}

class _CheckboxDemoState extends State<CheckboxDemo> {
  bool _apple = true;
  bool _pear = false;
  bool _banana = false;
  bool _wakeup = false;

  @override
  Widget build(BuildContext context) {
    return ListView(
      children: [
        ListTile(
          leading: Checkbox(
            value: _apple,
            // 取值可能为空
            onChanged: (bool? val) {
              setState(() {
                _apple = val!;
              });
            },
          ),
          title: Text('苹果,状态:$_apple'),
        ),
        ListTile(
          leading: Checkbox(
            value: _pear,
            // 取值可能为空
            onChanged: (bool? val) {
              setState(() {
                _pear = val!;
              });
            },
          ),
          title: Text('大鸭梨,状态:$_pear'),
        ),
        ListTile(
          leading: Checkbox(
            value: _banana,
            // 取值可能为空
            onChanged: (bool? val) {
              setState(() {
                _banana = val!;
              });
            },
            // 选中时,复选框的背景颜色
            activeColor: Colors.yellow,
            // 选中时,钩子的颜色
            checkColor: Colors.red,
          ),
          title: Text('香蕉,状态:$_banana'),
        ),
        // timeDilation 会让动画效果慢下来
        CheckboxListTile(
          title: const Text('Animate Slowly'),
          value: timeDilation != 1.0,
          onChanged: (bool? value) {
            setState(() {
              timeDilation = value! ? 10.0 : 1.0;
            });
          },
          secondary: const Icon(Icons.hourglass_empty),
        ),
        CheckboxListTile(
          value: _wakeup,
          onChanged: (bool? val) {
            setState(() {
              _wakeup = val!;
            });
          },
          // 主标题
          title: const Text('7:00'),
          // 子标题
          subtitle: const Text('起床上学啦!'),
          // 图标
          secondary: const Icon(Icons.alarm),
          // 选中时的背景色
          activeColor: Colors.green,
          // 选中时钩子的颜色
          checkColor: Colors.red,
          // 选中时,图标和文本也用 activeColor 重新渲染
          selected: _wakeup,
        ),
      ],
    );
  }
}

 

表单 -- Radio

Radio(单选框)
  value:开关的值,一般与状态字段绑定
  onChanged:开关状态变更时调用
  groupValue:选择组的值

RadioListTile(单选列表)
  value:开关的值,一般与状态字段绑定
  onChanged:开关状态变更时调用
  groupValue:选择组的值
import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Radio Demo'),
      ),
      body: const RadioDemo(),
    );
  }
}

class RadioDemo extends StatefulWidget {
  const RadioDemo({Key? key}) : super(key: key);

  @override
  State<RadioDemo> createState() => _RadioDemoState();
}

class _RadioDemoState extends State<RadioDemo> {
  dynamic gender;
  @override
  Widget build(BuildContext context) {
    return ListView(
      children: [
        Row(
          children: [
            const Text(''),
            Radio(
              value: 1,
              groupValue: gender,
              onChanged: (value) {
                setState(() {
                  gender = value;
                });
              },
            ),
            const Text(''),
            Radio(
              value: 2,
              groupValue: gender,
              onChanged: (value) {
                setState(() {
                  gender = value;
                });
              },
            ),
          ],
        ),
        RadioListTile(
          value: 1,
          groupValue: gender,
          onChanged: (value) {
            setState(() {
              gender = value;
            });
          },
          title: const Text(''),
          subtitle: const Text('male'),
          secondary: const Icon(Icons.person),
        ),
        RadioListTile(
          value: 2,
          groupValue: gender,
          onChanged: (value) {
            setState(() {
              gender = value;
            });
          },
          title: const Text(''),
          subtitle: const Text('female'),
          secondary: const Icon(Icons.person),
          // 选中的颜色
          activeColor: Colors.yellow,
          // 选中时,文本和按钮会用 activeColor 渲染
          selected: gender == 2,
        ),
      ],
    );
  }
}

 

表单 -- TextField

属性:
autofocus:是否获取焦点
keyboardType:键盘类型
obsureText:设置为密码框
decoration:样式修饰
onChanged:内容更改时自动调用 - value
labelText:标题
hintText:提示文字 - placeholder
maxLines:显示行数 - 文本域
import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('TextField Demo'),
      ),
      body: const TextFieldDemo(),
    );
  }
}

class TextFieldDemo extends StatefulWidget {
  const TextFieldDemo({Key? key}) : super(key: key);

  @override
  State<TextFieldDemo> createState() => _TextFieldDemoState();
}

class _TextFieldDemoState extends State<TextFieldDemo> {
  String phone = '';
  String password = '';
  String description = '';

  _register() {
    print('phone: $phone'); // phone: 12365412569
    print('password: $password'); // phone: 12365412569
    print('description: $description'); // description: srttg tutu edghh
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.all(10),
      child: ListView(
        children: [
          // 手机号
          TextField(
            autofocus: true,
            keyboardType: TextInputType.phone,
            decoration: const InputDecoration(
              prefixIcon: Icon(Icons.mobile_screen_share),
              labelText: '手机号',
              hintText: '请输入手机号',
              hintStyle: TextStyle(
                color: Colors.pink,
                fontSize: 14,
              ),
              // 聚焦时边框的样式
              focusedBorder: UnderlineInputBorder(
                borderSide: BorderSide(
                  color: Colors.green,
                ),
              ),
              // 默认边框样式
              enabledBorder: UnderlineInputBorder(
                borderSide: BorderSide(
                  color: Colors.yellow,
                ),
              ),
            ),
            maxLength: 11,
            onChanged: (value) {
              setState(() {
                phone = value;
              });
            },
          ),
          // 密码
          TextField(
            // 隐藏文本
            obscureText: true,
            keyboardType: TextInputType.text,
            decoration: const InputDecoration(
              prefixIcon: Icon(Icons.code_outlined),
              labelText: '密码',
              hintText: '请输入密码',
            ),
            onChanged: (value) {
              setState(() {
                password = value;
              });
            },
          ),
          // 文本域
          TextField(
            keyboardType: TextInputType.text,
            decoration: const InputDecoration(
              prefixIcon: Icon(Icons.person),
              labelText: '简介',
              hintText: '请简要介绍一下自己',
            ),
            maxLines: 3,
            onChanged: (value) {
              setState(() {
                description = value;
              });
            },
          ),
          // 按钮
          Container(
            width: double.infinity,
            padding: const EdgeInsets.all(20),
            child: ElevatedButton(
              child: const Text('提交'),
              onPressed: () {
                _register();
              },
            ),
          ),
        ],
      ),
    );
  }
}

 

表单 -- 日历

CalendarDatePicker(日历选择器)

属性:
initialCalendarMode
  DatePickerMode.day
  DatePickerMode.year

showDatePicker(日期选择器)

属性:
initialDatePickerMode (year | day)
initialEntryMode (calendar | input)

showTimePicker(时间选择器)
import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Calendar Demo'),
      ),
      body: const CalendarDemo(),
    );
  }
}

class CalendarDemo extends StatefulWidget {
  const CalendarDemo({Key? key}) : super(key: key);

  @override
  State<CalendarDemo> createState() => _CalendarDemoState();
}

class _CalendarDemoState extends State<CalendarDemo> {
  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.all(15),
      child: ListView(
        children: [
          _showDatePicker(context),
          _showDatePickerForYear(context),
        ],
      ),
    );
  }

  // 日期选择器
  ElevatedButton _showDatePicker(context) {
    return ElevatedButton(
      onPressed: () {
        showDatePicker(
            context: context,
            // 日期选择模式,取值为 day 或 year
            initialDatePickerMode: DatePickerMode.day,
            // 初始化选中日期
            initialDate: DateTime.now(),
            // 开始日期
            firstDate: DateTime(2022, 5),
            // 结束日期
            lastDate: DateTime(2022, 12),
            // 日历弹框样式,默认:calendar
            initialEntryMode: DatePickerEntryMode.calendar,
            // 当前日期
            currentDate: DateTime.now(),
            // 左上方提示
            helpText: '日期选择器',
            // 取消按钮文案
            cancelText: '取消',
            // 确认按钮文案
            confirmText: '确定',
            // 格式错误提示
            errorFormatText: 'Input format error',
            // 输入不在 first 与 last 之间日期提示
            errorInvalidText: 'Out of date range',
            // 输入框上方提示
            fieldLabelText: '请输入日期',
            // 输入框为空时内部提示
            fieldHintText: '输入日期不能为空',
            // 是否为根导航器
            useRootNavigator: true,
            // 设置不可选日期
            selectableDayPredicate: (dateTime) {
              if (dateTime == DateTime(2022, 10, 1)) {
                return false;
              }
              return true;
            });
      },
      child: const Text('showDatePicker'),
    );
  }

  // 年份选择器
  ElevatedButton _showDatePickerForYear(context) {
    return ElevatedButton(
      onPressed: () {
        showDatePicker(
          context: context,
          // 初始化选中日期
          initialDate: DateTime(2019, 1, 1),
          // 开始日期
          firstDate: DateTime(2002),
          // 结束日期
          lastDate: DateTime(2066),
          // 当前日期
          currentDate: DateTime.now(),
          // 左上方提示
          helpText: '年份选择器',
          // 取消按钮文案
          cancelText: '取消',
          // 确认按钮文案
          confirmText: '确认',
        );
      },
      child: const Text('showYearPicker'),
    );
  }
}

 

表单 -- Form

使用步骤
(1)、创建表单 Form,并以 GlobalKey 作为唯一性标识
(2)、添加带验证逻辑的 TextFormField 到 Form 中
(3)、创建按钮以验证和提交表单

Form(表单容器)

  必填属性:
    key: GlobalKey
    child:子组件
  创建表单唯一键:final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  验证表单:_formKey.currentState.validate();
  提交表单:_formKey.currentState.save();
  重置表单:_formKey.currentState.reset();

TextFormField(输入框)
  与 TextField 的区别:必须在 Form 内使用 & 带有验证器
  validator:验证器
  obscureText:密码框
  onSaved:
    设定表单字段的值
    在表单的 save() 方法之后执行
import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  const Home({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Form Demo'),
      ),
      body: const FormStateDemo(),
    );
  }
}

class FormStateDemo extends StatefulWidget {
  const FormStateDemo({Key? key}) : super(key: key);

  @override
  State<FormStateDemo> createState() => _FormStateDemoState();
}

class _FormStateDemoState extends State<FormStateDemo> {
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  String _phone = '';
  String _password = '';
  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.all(20),
      child: Column(
        children: [
          Form(
            key: _formKey,
            child: Column(
              children: [
                // 手机号
                TextFormField(
                  decoration: const InputDecoration(
                    hintText: '手机号',
                  ),
                  // 校验
                  validator: (value) {
                    print('手机号 value: $value');
                    RegExp reg = RegExp(r'^\d{11}$');
                    if (!reg.hasMatch(value!)) {
                      print('error');
                      return '手机号码输入有误!';
                    }
                    return null;
                  },
                  // 设定表单字段的值
                  onSaved: (value) {
                    print('_phone onSaved');
                    _phone = value!;
                  },
                ),
                // 密码
                TextFormField(
                  decoration: const InputDecoration(
                    hintText: '密码',
                  ),
                  // 校验
                  validator: (value) {
                    print('密码 value: $value');
                    return value!.length < 6 ? '密码有误!' : null;
                  },
                  // 设定表单字段的值
                  onSaved: (value) {
                    print('_password onSaved');
                    _password = value!;
                  },
                ),
              ],
            ),
          ),
          Row(
            children: [
              Expanded(
                child: ElevatedButton(
                  onPressed: () {
                    if (_formKey.currentState!.validate()) {
                      print('提交成功!');
                      print('_formKey.currentState!.save() Before');
                      // 提交表单
                      _formKey.currentState!.save();
                      print('_formKey.currentState!.save() After');
                      print('_phone: $_phone');
                      print('_password: $_password');
                    }
                  },
                  child: const Text('提交'),
                ),
              ),
              const SizedBox(
                width: 20,
              ),
              Expanded(
                child: ElevatedButton(
                  onPressed: () {
                    _formKey.currentState!.reset();
                  },
                  child: const Text('重置'),
                ),
              ),
            ],
          ),
        ],
      ),
    );
  }
}

 

posted @ 2022-05-31 20:23  rogerwu  阅读(349)  评论(0编辑  收藏  举报