一、前言
flutter开发中,有时候的页面例如OA流程、贷款申请等等一系列的流程操作,必不可少的就是填写表单,在flutter中,表单会有很多种,例如“text”文本框,”options“下拉框、”select“选择框等等。为了减少冗余代码开发,各项目组公司会封装一套自己的自定义表单组件提供使用。但往往随着需求的更新、变化,当年公司封装的一套表单有时候并不能满足自己的实际需求。因此,个人也结合网上看到的内容,自己写一个简单的表单,目的是将表单中的一二级联动进行抽离(公司中封装的组件表单在联动一块稍有些瑕疵,影响功能),方便表单联动使用。表单的style仿照公司需要的表单style,具体UI如下:
二、代码层
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
typedef GestureTapCallback = void Function();
class ContentView extends StatelessWidget {
// 标题
final String title;
//是否必填的标志
final String mustType;
//输入框 显示的灰色提示文字
final String hintText;
final TextEditingController controller;
//下拉框数组
final List contentList;
// 输入框是否只读 默认 false
final bool readOnly;
//文字显示的位置
final TextAlign textAlign;
//输入框键盘样式
final TextInputType keyboardType;
//输入框右边👉显示的widget
/*
*suffixIcon: Container(
width: 40,
height: 40,
child: Icon(Icons.format_list_bulleted),
alignment: Alignment.centerRight,
),
*/
final Widget suffixIcon;
//判断 类型 是 输入 还是 下拉选择
final bool style;
// 下拉框点击事件
final ValueChanged<String> onChanged;
// 输入框输入的类型限制,只能输入数字、汉字等
final List<TextInputFormatter> inputFormatters;
// 输入框不可输入时的点击事件
final GestureTapCallback onTap;
//光标焦点
final FocusNode focusNode;
//输入框左边title的宽度
final num titleWidth;
ContentView({
this.title = '',
this.mustType = '',
this.hintText = '',
this.controller,
this.contentList,
this.readOnly = false,
this.textAlign,
this.keyboardType,
this.suffixIcon,
this.style = false,
this.onChanged,
this.inputFormatters,
this.onTap,
this.focusNode,
this.titleWidth,
});
factory ContentView.textfield({
String title = '',
String mustType = '',
String hintText = '',
@required TextEditingController controller,
//是否只读
bool readOnly = false,
//光标开始位置
TextAlign textAlign = TextAlign.right,
TextInputType keyboardType,
Widget suffixIcon,
ValueChanged<String> onChanged,
List<TextInputFormatter> inputFormatters,
GestureTapCallback onTap,
FocusNode focusNode,
num titleWidth,
}) {
return ContentView(
controller: controller,
title: title,
mustType: mustType,
hintText: hintText,
readOnly: readOnly,
textAlign: textAlign,
keyboardType: keyboardType,
suffixIcon: suffixIcon,
style: false,
onChanged: onChanged,
inputFormatters: inputFormatters,
onTap: onTap,
focusNode: focusNode,
titleWidth: titleWidth,
);
}
factory ContentView.dropdownView({
String title = '',
String mustType = '',
String hintText = '',
@required TextEditingController controller,
@required List contentList,
TextAlign textAlign = TextAlign.right,
ValueChanged<String> onChanged,
num titleWidth,
}) {
return ContentView(
controller: controller,
title: title,
mustType: mustType,
hintText: hintText,
contentList: contentList,
textAlign: textAlign,
style: true,
onChanged: onChanged,
titleWidth: titleWidth,
);
}
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Container(
color: Colors.white,
child: ListTile(
title: Row(
children: <Widget>[
Text(
mustType,
style: TextStyle(color: Colors.red),
),
Text(
title,
style: TextStyle(fontSize: 16),
),
],
),
trailing: Container(
padding: EdgeInsets.fromLTRB(0, 0, 20, 0),
child: this.style == false
? TextField(
keyboardType: this.keyboardType,
readOnly: this.readOnly,
controller: controller,
textAlign: this.textAlign,
onChanged: this.onChanged,
inputFormatters: this.inputFormatters,
onTap: this.onTap,
focusNode: focusNode,
decoration: InputDecoration(
border: InputBorder.none,
hintText: hintText,
hintStyle: TextStyle(fontSize: 16),
suffixIcon: this.suffixIcon,
),
)
: DropdownButtonFormField(
decoration: InputDecoration(
border: InputBorder.none,
hintText: hintText,
hintStyle: TextStyle(fontSize: 16),
contentPadding: EdgeInsets.fromLTRB(0, 0, 0, 0),
),
value: controller.text == '' ? null : controller.text,
items: contentList
.map((title) => DropdownMenuItem(
child: Center(
child: Text(title),
),
value: title,
))
.toList(),
onChanged: (title) {
// setState(() {
controller.text = title;
this.onChanged(title);
// });
}),
width: MediaQuery.of(context).size.width -
(this.titleWidth == null ? 136 : this.titleWidth),
),
),
),
Divider(
height: 1,
),
],
);
}
}
若当前ui页面有用到的同学,可以私信我一起交流下数据交互问题,暂时就不写下来了