Flutter表单动画包装插件form_animate_wrap的使用
Flutter表单动画包装插件form_animate_wrap的使用
Animated wrappers可以用来包裹TextFormField
以获得一些不错的交互效果。
安装
在你的Flutter项目的pubspec.yaml
文件中添加以下依赖:
form_animate_wrap: ^0.0.6
然后在你需要使用的文件中导入它:
import 'package:form_animate_wrap/form_animate_wrap.dart';
使用
动画验证器(Anime Validator)

此包装器可用于包裹TextFormField
,如果需要在事件如验证错误时添加动画效果。
TextEditingController firstNameController = TextEditingController();
AnimeValidator(
enableAnimation: true,
child: CustomTextFormField(
controller: firstNameController,
hintTextVal: "First Name",
)),
荧光选择器(Glow Selector)

此包装器可用于识别选中的TextFormField
。如果有多个TextFormField
,这将有助于快速识别选中的字段。
FocusNode firstNameNode = FocusNode();
GlowSelector(
borderRadius: 15,
enableFocusGlowing: true,
focusGlowColor: Colors.blueAccent,
focusNode: firstNameNode,
child: CustomTextFormField(
focusNode: firstNameNode,
hintTextVal: "First Name",
)),
荧光验证器(Glow Validator)

此包装器可用于基于条件验证TextField
。例如,你可以在提交表单时设置包装器以高亮显示空文本框。
TextEditingController firstNameController = TextEditingController();
GlowValidator(
borderRadius: 15,
enableAnimation: true,
child: CustomTextFormField(
controller: firstNameController,
hintTextVal: "First Name",
)),
示例代码
以下是完整的示例代码:
import 'package:animated_validator/widgets/custom_text_input.dart';
import 'package:flutter/material.dart';
import 'package:form_animate_wrap/form_animate_wrap.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// 此小部件是您的应用程序的根。
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Form Animate Wrap 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> {
bool isSubmittedAnimeValidator = false;
bool isSubmittedGlowValidator = false;
TextEditingController avFirstNameController = TextEditingController();
TextEditingController avLastNameController = TextEditingController();
TextEditingController avEmailController = TextEditingController();
TextEditingController gvFirstNameController = TextEditingController();
TextEditingController gvLastNameController = TextEditingController();
TextEditingController gvEmailController = TextEditingController();
FocusNode firstNameNode = FocusNode();
FocusNode lastNameNode = FocusNode();
FocusNode emailNode = FocusNode();
[@override](/user/override)
Widget build(BuildContext context) {
double height = MediaQuery.of(context).size.height;
double width = MediaQuery.of(context).size.width;
double appbarHeight = AppBar().preferredSize.height;
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: PageView(
children: [
Container(
color: Colors.white,
child: SingleChildScrollView(
child: Center(
child: SizedBox(
width: width * 0.8,
height: height - appbarHeight,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(
height: height * 0.5,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
const Text(
"Anime Validators",
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.black),
),
AnimeValidator(
enableAnimation:
getAVValidity(avFirstNameController),
child: CustomTextFormField(
controller: avFirstNameController,
hintTextVal: "First Name",
)),
AnimeValidator(
enableAnimation:
getAVValidity(avLastNameController),
child: CustomTextFormField(
controller: avLastNameController,
hintTextVal: "Last Name",
)),
AnimeValidator(
enableAnimation:
getAVValidity(avEmailController),
child: CustomTextFormField(
controller: avEmailController,
hintTextVal: "Email",
)),
],
),
),
Padding(
padding: const EdgeInsets.only(bottom: 50),
child: GestureDetector(
onTap: () {
setState(() {
isSubmittedAnimeValidator = true;
});
},
child: Container(
decoration: BoxDecoration(
color: Colors.lightBlue,
borderRadius: BorderRadius.circular(15)),
width: width * 0.8,
child: const Padding(
padding: EdgeInsets.all(16.0),
child: Text(
"Submit",
style: TextStyle(
fontSize: 20,
color: Colors.white,
fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
),
),
),
),
),
],
),
),
),
),
),
Container(
color: Colors.white,
child: SingleChildScrollView(
child: Center(
child: SizedBox(
width: width * 0.8,
height: height - appbarHeight,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(
height: height * 0.5,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
const Text(
"Glow Selector",
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.black),
),
GlowSelector(
borderRadius: 15,
enableFocusGlowing: true,
focusGlowColor: Colors.blueAccent,
focusNode: firstNameNode,
child: CustomTextFormField(
focusNode: firstNameNode,
hintTextVal: "First Name",
)),
GlowSelector(
borderRadius: 15,
enableFocusGlowing: true,
focusNode: lastNameNode,
focusGlowColor: Colors.green,
child: CustomTextFormField(
focusNode: lastNameNode,
hintTextVal: "Last Name",
)),
GlowSelector(
borderRadius: 15,
enableFocusGlowing: true,
focusNode: emailNode,
focusGlowColor: Colors.red,
child: CustomTextFormField(
focusNode: emailNode,
hintTextVal: "Email",
))
],
),
),
Padding(
padding: const EdgeInsets.only(bottom: 50),
child: GestureDetector(
onTap: () {},
child: Container(
decoration: BoxDecoration(
color: Colors.lightBlue,
borderRadius: BorderRadius.circular(15)),
width: width * 0.8,
child: const Padding(
padding: EdgeInsets.all(16.0),
child: Text(
"Submit",
style: TextStyle(
fontSize: 20,
color: Colors.white,
fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
),
),
),
),
),
],
),
),
),
),
),
Container(
color: Colors.white,
child: SingleChildScrollView(
child: Center(
child: SizedBox(
width: width * 0.8,
height: height - appbarHeight,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(
height: height * 0.5,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
const Text(
"Glow Validators",
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.black),
),
GlowValidator(
borderRadius: 15,
enableAnimation:
getGVValidity(gvFirstNameController),
child: CustomTextFormField(
controller: gvFirstNameController,
hintTextVal: "First Name",
)),
GlowValidator(
borderRadius: 15,
enableAnimation:
getGVValidity(gvLastNameController),
child: CustomTextFormField(
controller: gvLastNameController,
hintTextVal: "Last Name",
)),
GlowValidator(
borderRadius: 15,
enableAnimation:
getGVValidity(gvEmailController),
child: CustomTextFormField(
controller: gvEmailController,
hintTextVal: "Email",
)),
],
),
),
Padding(
padding: const EdgeInsets.only(bottom: 50),
child: GestureDetector(
onTap: () {
setState(() {
isSubmittedGlowValidator = true;
});
},
child: Container(
decoration: BoxDecoration(
color: Colors.lightBlue,
borderRadius: BorderRadius.circular(15)),
width: width * 0.8,
child: const Padding(
padding: EdgeInsets.all(16.0),
child: Text(
"Submit",
style: TextStyle(
fontSize: 20,
color: Colors.white,
fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
),
),
),
),
),
],
),
),
),
),
),
],
),
);
}
bool getAVValidity(TextEditingController controller) {
if ((isSubmittedAnimeValidator && controller.text.isNotEmpty) ||
(!isSubmittedAnimeValidator && controller.text.isNotEmpty)) {
return false;
} else {
if (isSubmittedAnimeValidator) {
return true;
} else {
return false;
}
}
}
bool getGVValidity(TextEditingController controller) {
if ((isSubmittedGlowValidator && controller.text.isNotEmpty) ||
(!isSubmittedGlowValidator && controller.text.isNotEmpty)) {
return false;
} else {
if (isSubmittedGlowValidator) {
return true;
} else {
return false;
}
}
}
}
更多关于Flutter表单动画包装插件form_animate_wrap的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter表单动画包装插件form_animate_wrap的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
form_animate_wrap
是一个Flutter插件,用于在表单提交时添加动画效果,例如加载动画、成功或失败的提示动画等。这个插件可以帮助你在表单提交过程中提供更好的用户体验。
安装
首先,你需要在 pubspec.yaml
文件中添加 form_animate_wrap
依赖:
dependencies:
flutter:
sdk: flutter
form_animate_wrap: ^1.0.0 # 请检查最新版本
然后运行 flutter pub get
来安装依赖。
使用
form_animate_wrap
提供了一个 FormAnimateWrap
小部件,你可以将表单内容包裹在其中,并在表单提交时显示动画。
基本用法
import 'package:flutter/material.dart';
import 'package:form_animate_wrap/form_animate_wrap.dart';
class MyForm extends StatefulWidget {
@override
_MyFormState createState() => _MyFormState();
}
class _MyFormState extends State<MyForm> {
final _formKey = GlobalKey<FormState>();
String _name = '';
Future<void> _submitForm() async {
if (_formKey.currentState!.validate()) {
_formKey.currentState!.save();
// 模拟网络请求
await Future.delayed(Duration(seconds: 2));
// 这里可以处理提交逻辑
print('Name: $_name');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Form Animate Wrap Example'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: FormAnimateWrap(
onSubmit: _submitForm,
child: Form(
key: _formKey,
child: Column(
children: [
TextFormField(
decoration: InputDecoration(labelText: 'Name'),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter your name';
}
return null;
},
onSaved: (value) {
_name = value!;
},
),
SizedBox(height: 16),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
_submitForm();
}
},
child: Text('Submit'),
),
],
),
),
),
),
);
}
}
参数说明
onSubmit
: 表单提交时触发的异步函数。在这个函数中,你可以处理表单提交的逻辑。child
: 包裹的表单内容。loadingWidget
: 自定义加载动画,默认是一个CircularProgressIndicator
。successWidget
: 自定义成功提示动画,默认是一个图标和文本。errorWidget
: 自定义错误提示动画,默认是一个图标和文本。
自定义动画
你可以通过 loadingWidget
、successWidget
和 errorWidget
参数来自定义动画:
FormAnimateWrap(
onSubmit: _submitForm,
loadingWidget: Center(child: Text('Loading...')),
successWidget: Center(child: Icon(Icons.check, color: Colors.green)),
errorWidget: Center(child: Icon(Icons.error, color: Colors.red)),
child: Form(
key: _formKey,
child: Column(
children: [
// 表单字段
],
),
),
)