一、表单封装组件实现效果
//表单组件
Widget buildFormWidget(List<InputModel> formList,{required GlobalKey<FormState> formKey}) {return Form(key: formKey,child: Column(children: formList.map((item) {return Column(crossAxisAlignment: CrossAxisAlignment.start,children: [Row(children: [item.isRequired? Icon(Icons.star,size: 10,color: Theme.of(Get.context!).colorScheme.error): SizedBox(),Text(item.label,style:Theme.of(Get.context!).inputDecorationTheme.labelStyle,)],),SizedBox(height: 16,),GestureDetector(onTap: item.type == 'select'? () {showBottomSheet(item.bottomSheetList!, item.label,selectProp: item.selectProp,selectController: item.selectController,controller: item.controller);}: null,child: TextFormField(controller: item.controller,enabled: item.type == 'text',keyboardType: item.keyboardType,validator: (value) {// 添加表单验证if (item.isRequired && (value == null || value.isEmpty)) {return '请${item.type == 'select' ? '选择' : '输入'}${item.label}';}//正则表达式验证if (item.pattern.isEmpty &&(value == null || value.isEmpty)) {RegExp regex = RegExp(item.pattern);if (!regex.hasMatch(value!)) {return '请输入正确的${item.label}';}}return null;},decoration: InputDecoration(suffixIcon: item.type == 'select'? Icon(Icons.arrow_forward_ios,color: Color(0x6615171E)): null,focusedBorder: Theme.of(Get.context!).inputDecorationTheme.focusedBorder,disabledBorder: Theme.of(Get.context!).inputDecorationTheme.disabledBorder,enabledBorder: Theme.of(Get.context!).inputDecorationTheme.enabledBorder,errorBorder:Theme.of(Get.context!).inputDecorationTheme.errorBorder,errorStyle:Theme.of(Get.context!).inputDecorationTheme.errorStyle,hintText:'请${item.type == 'select' ? '选择' : '输入'}${item.label}',isDense: true,filled: true,fillColor:Theme.of(Get.context!).inputDecorationTheme.fillColor,),),),SizedBox(height: 16,),],);}).toList(),));
}//bottomSheet
void showBottomSheet(List<Map<String, dynamic>> list, String title,{Map? selectProp,RxMap<String, dynamic>? selectController,TextEditingController? controller}) {showGenderPanel(title,buildCheckList(list, (item) {controller?.text = item[selectProp?['label']];Get.back();}, props: selectProp, selected: selectController));
}// 底部弹出层
void showGenderPanel(String title, Widget sheetContent) {showModalBottomSheet(context: Get.context!,builder: (context) {return Container(height: 800,child: Column(children: [Container(// height: 100,padding: Theme.of(Get.context!).dialogTheme.actionsPadding,child: Stack(children: [Row(mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[Text(title,overflow: TextOverflow.ellipsis, // 显示省略号style: Theme.of(Get.context!).dialogTheme.titleTextStyle,),],),Positioned(right: 20,// top: 14,child: GestureDetector(onTap: () {Navigator.pop(context);},child: Icon(Icons.cancel_outlined,color: Theme.of(Get.context!).dialogTheme.iconColor),),),],)),Divider(height: 1,// color: Theme.of(Get.context!).dividerColor,),Container(// padding: EdgeInsets.all(16),child: sheetContent,)],));});
}//单选列表
Widget buildCheckList(List<Map<String, dynamic>> list, Function? onChanged,{Map? props, RxMap<String, dynamic>? selected}) {props ??= {'label': 'label', 'value': 'value'};String label = props['label'] ?? 'label';String value = props['value'] ?? 'value';return Obx(() => Container(width: Get.width,child: Column(children: list.asMap().entries.map((entry) {int index = entry.key;dynamic item = entry.value;print('渲染');return Column(children: [GestureDetector(onTap: () {selected?.value = item;if (onChanged != null) {onChanged(item);}},child: Container(width: Get.width,decoration: BoxDecoration(color: Colors.blue.withOpacity(0),),padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 16),child: Row(children: [Icon((selected?.value[value] ?? '') == item[value]? Icons.check_circle: Icons.circle_outlined,size: 22,color: (selected?.value[value] ?? '') == item[value]? Color.fromRGBO(50, 73, 223, 1): Color.fromRGBO(21, 23, 30, 0.40)),SizedBox(width: 6),Text(item[label],style: TextStyle(fontSize: 16,),),],),)),Divider(height: 1,color: index + 1 == list.length? Color.fromRGBO(128, 130, 145, 0): Color.fromRGBO(128, 130, 145, 0.20),),],);}).toList(),)));
}
二、调用方法:
buildFormWidget(formList, formKey: formKey),
三、数据格式:
Map<String, dynamic> controllers = {'phone': TextEditingController(text: '仓库1'),'phoneSelect': <String, dynamic>{'id': '18', 'name': '仓库1'}.obs,'code': TextEditingController(text: '123'),};formList = [InputModel(label: '入库仓库',isRequired: true,type: 'select',controller: controllers['phone'],selectController: controllers['phoneSelect'],bottomSheetList: bottomSheetList,selectProp: {'label': 'name', 'value': 'id'}),InputModel(label: '入库数量',isRequired: true,keyboardType: TextInputType.number,controller: controllers['code']),];