Flutter文本表单验证插件textformfield_unit的使用
Flutter 文本表单验证插件 textformfield_unit 的使用
概述
TextFormField
小部件带有一个下拉列表用于单位选择,并提供转换功能。
使用方法
你可以几乎像使用原始的 TextFormField
一样来使用它,但需要添加一些额外的功能。
首先,它有一个泛型类型,即你想要使用的单位类型。假设我们需要以下三个长度单位:
enum SizeUnits { Millimeter, Inch, LightNanosecond }
我们准备一个映射,包含用户可读的名称:
static final unitNames = {
SizeUnits.Millimeter: 'mm',
SizeUnits.Inch: '"',
SizeUnits.LightNanosecond: 'light-ns',
};
还需要一个函数,该函数可以接收一个值并将其从一种单位转换为另一种单位:
double _sizeConverter(SizeUnits fromUnit, SizeUnits toUnit, double value) {
final valueMm = switch (fromUnit) {
SizeUnits.Millimeter => value,
SizeUnits.Inch => value * 25.4,
SizeUnits.LightNanosecond => value * 299.792458,
};
return switch (toUnit) {
SizeUnits.Millimeter => valueMm,
SizeUnits.Inch => valueMm / 25.4,
SizeUnits.LightNanosecond => valueMm / 299.792458,
};
}
我们将这些参数(以及其他任何通常的 TextFormField
参数)传递给字段:
TextFormUnitField<SizeUnits>(
controller: controller,
keyboardType: TextInputType.number,
inputFormatters: [FilteringTextInputFormatter.allow(allowed)],
textInputAction: TextInputAction.next,
icon: const Icon(Icons.height),
labelText: 'Size',
units: unitNames,
initialUnit: SizeUnits.Millimeter,
unitIcon: const Icon(Icons.keyboard_arrow_down),
converter: _sizeConverter,
onSaved: (value) {
if (value != null) print('${value.value} ${unitNames[value.unit]}');
},
),
当它调用回调进行验证或保存时,它会传递一个 ValueWithUnit<T>
类型的值,其中 T
是我们的单位类型。
完整示例
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:intl/intl.dart';
import 'package:textformfield_unit/textformfield_unit.dart';
enum SizeUnits { Millimeter, Inch, LightNanosecond, Twip, Thou, Barleycorn, Foot, Yard, Chain, Furlong, Mile, League, Fathom, NauticalMile, Link, Rod }
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'TextFormFieldUnit Demo',
theme: ThemeData(primarySwatch: Colors.blue),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
[@override](/user/override)
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
static final unitNames = {
SizeUnits.Millimeter: 'mm',
SizeUnits.Inch: 'in',
SizeUnits.LightNanosecond: 'light-ns',
SizeUnits.Twip: 'twip',
SizeUnits.Thou: 'th',
SizeUnits.Barleycorn: 'Bc',
SizeUnits.Foot: 'ft',
SizeUnits.Yard: 'yd',
SizeUnits.Chain: 'ch',
SizeUnits.Furlong: 'fur',
SizeUnits.Mile: 'mi',
SizeUnits.League: 'lea',
SizeUnits.Fathom: 'ftm',
SizeUnits.NauticalMile: 'nmi',
SizeUnits.Link: 'links',
SizeUnits.Rod: 'rods',
};
final formKey = GlobalKey<FormState>();
late TextEditingController controller;
[@override](/user/override)
void initState() {
super.initState();
controller = TextEditingController(text: NumberFormat.decimalPattern().format(156.25));
}
[@override](/user/override)
void dispose() {
super.dispose();
controller.dispose();
}
double _sizeConverter(SizeUnits fromUnit, SizeUnits toUnit, double value) {
final valueMm = switch (fromUnit) {
SizeUnits.Millimeter => value,
SizeUnits.Inch => value * 25.4,
SizeUnits.LightNanosecond => value * 299.792458,
SizeUnits.Twip => value * 0.0176389,
SizeUnits.Thou => value * 0.0254,
SizeUnits.Barleycorn => value * 8.4667,
SizeUnits.Foot => value * 0304.8,
SizeUnits.Yard => value * 914.4,
SizeUnits.Chain => value * 20116.8,
SizeUnits.Furlong => value * 201168,
SizeUnits.Mile => value * 1609344,
SizeUnits.League => value * 4828032,
SizeUnits.Fathom => value * 1852,
SizeUnits.NauticalMile => value * 1852,
SizeUnits.Link => value * 0201.168,
SizeUnits.Rod => value * 5029.2,
};
return switch (toUnit) {
SizeUnits.Millimeter => valueMm,
SizeUnits.Inch => valueMm / 25.4,
SizeUnits.LightNanosecond => valueMm / 299.792458,
SizeUnits.Twip => valueMm / 0.0176389,
SizeUnits.Thou => valueMm / 0.0254,
SizeUnits.Barleycorn => valueMm / 8.4667,
SizeUnits.Foot => valueMm / 0304.8,
SizeUnits.Yard => valueMm / 914.4,
SizeUnits.Chain => valueMm / 20116.8,
SizeUnits.Furlong => valueMm / 201168,
SizeUnits.Mile => valueMm / 1609344,
SizeUnits.League => valueMm / 4828032,
SizeUnits.Fathom => valueMm / 1852,
SizeUnits.NauticalMile => valueMm / 1852,
SizeUnits.Link => valueMm / 0201.168,
SizeUnits.Rod => valueMm / 5029.2,
};
}
[@override](/user/override)
Widget build(BuildContext context) {
final allowed = switch (NumberFormat().symbols.DECIMAL_SEP) {
'.' => RegExp(r'[\d.]'),
',' => RegExp(r'[\d,]'),
_ => RegExp(r'\d'),
};
return Scaffold(
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Form(
key: formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextFormUnitField<SizeUnits>(
controller: controller,
keyboardType: TextInputType.number,
inputFormatters: [FilteringTextInputFormatter.allow(allowed)],
textInputAction: TextInputAction.next,
icon: const Icon(Icons.height),
labelText: 'Size',
units: unitNames,
initialUnit: SizeUnits.Millimeter,
unitIcon: const Icon(Icons.keyboard_arrow_down),
converter: _sizeConverter,
onSaved: (value) {
if (value != null) print('${value.value} ${unitNames[value.unit]}');
},
),
],
)),
ElevatedButton(
onPressed: () {
if (formKey.currentState!.validate()) {
formKey.currentState!.save();
}
},
child: const Text('Save'),
),
],
),
),
);
}
}
更多关于Flutter文本表单验证插件textformfield_unit的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
1 回复
更多关于Flutter文本表单验证插件textformfield_unit的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
TextFormField
是 Flutter 中用于构建表单输入字段的常用小部件。它允许你轻松地验证用户输入,并提供反馈以帮助用户正确填写表单。虽然 Flutter 本身并没有名为 textformfield_unit
的插件,但你可以通过自定义 TextFormField
来实现各种验证功能。
以下是一个简单的示例,展示了如何使用 TextFormField
进行基本的文本验证:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('TextFormField Validation Example'),
),
body: MyCustomForm(),
),
);
}
}
class MyCustomForm extends StatefulWidget {
[@override](/user/override)
_MyCustomFormState createState() => _MyCustomFormState();
}
class _MyCustomFormState extends State<MyCustomForm> {
final _formKey = GlobalKey<FormState>();
[@override](/user/override)
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
TextFormField(
decoration: InputDecoration(
labelText: 'Enter your email',
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter some text';
}
if (!RegExp(r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+")
.hasMatch(value)) {
return 'Please enter a valid email address';
}
return null;
},
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: ElevatedButton(
onPressed: () {
// Validate returns true if the form is valid, or false otherwise.
if (_formKey.currentState!.validate()) {
// If the form is valid, display a snackbar. In the real world,
// you'd often call a server or save the information in a database.
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Processing Data')),
);
}
},
child: Text('Submit'),
),
),
],
),
);
}
}