import 'package:flutter/material.dart'; import 'package:qhd_prevention/customWidget/toast_util.dart'; import '../http/ApiService.dart'; import '../tools/tools.dart'; /// 自定义组件 class ListItemFactory { /// 类型1:横向spaceBetween布局两个文本加按钮 static Widget createRowSpaceBetweenItem({ required String leftText, required String rightText, double verticalPadding = 10, double horizontalPadding = 0, Color textColor = Colors.black, bool isRight = false, bool isRequired = false, }) { return Padding( padding: EdgeInsets.symmetric( vertical: verticalPadding, horizontal: horizontalPadding, ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( children: [ if (isRequired) Text('* ', style: TextStyle(color: Colors.red)), Text( leftText, style: TextStyle( fontSize: 15, fontWeight: FontWeight.bold, color: textColor, ), ), ], ), if (isRight) Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( _truncateText(rightText, 100), // rightText, style: TextStyle(fontSize: 15, color: Colors.grey), ), SizedBox(width: 2), Icon( Icons.arrow_forward_ios_rounded, color: Colors.black45, size: 15, ), ], ) else Text(rightText, style: TextStyle(fontSize: 15, color: Colors.grey)), ], ), ); } // 辅助函数:截断文本 static String _truncateText(String text, int maxLength) { if (text.length <= maxLength) return text; return text.substring(0, maxLength) + '...'; } ///类型2:上下布局两个文本(自适应高度) static Widget createColumnTextItem({ required String topText, required String bottomText, double verticalPadding = 15, double horizontalPadding = 0, }) { return Padding( padding: EdgeInsets.symmetric( vertical: verticalPadding, horizontal: horizontalPadding, ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ Text( topText, style: TextStyle( fontSize: 15, fontWeight: FontWeight.bold, color: Colors.black, ), ), const SizedBox(height: 5), Text( bottomText, style: TextStyle(fontSize: 15, color: Colors.grey), softWrap: true, maxLines: null, // 允许无限行数 ), ], ), ); } /// 类型3:文本和图片上下布局 static Widget createTextImageItem({ required String text, required List imageUrls, double imageHeight = 90, double verticalPadding = 10, double horizontalPadding = 0, // 点击图片时回调,index 为被点击图片的下标 void Function(int index)? onImageTapped, }) { return Padding( padding: EdgeInsets.symmetric( vertical: verticalPadding, horizontal: horizontalPadding, ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( text, style: const TextStyle( fontSize: 15, fontWeight: FontWeight.bold, color: Colors.black, ), ), const SizedBox(height: 10), Wrap( spacing: 8, // 水平间距 runSpacing: 8, // 垂直间距 children: List.generate(imageUrls.length, (i) { final url = ApiService.baseImgPath + imageUrls[i]; Widget img; if (url.startsWith('http')) { img = Image.network( url, height: imageHeight, width: imageHeight * 3 / 2, fit: BoxFit.cover, ); } else { img = Image.asset( url, height: imageHeight, width: imageHeight * 3 / 2, fit: BoxFit.cover, ); } return GestureDetector( onTap: () { if (onImageTapped != null) onImageTapped(i); }, child: ClipRRect( borderRadius: BorderRadius.circular(4), child: img, ), ); }), ), ], ), ); } /// 类型6:文本和视频上下布局 static Widget createTextVideoItem({ required String text, required String videoUrl, double videoHeight = 90, double verticalPadding = 10, double horizontalPadding = 0, VoidCallback? onVideoTapped, }) { return Padding( padding: EdgeInsets.symmetric( vertical: verticalPadding, horizontal: horizontalPadding, ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( text, style: const TextStyle( fontSize: 15, fontWeight: FontWeight.bold, color: Colors.black, ), ), const SizedBox(height: 10), videoUrl.isNotEmpty ? GestureDetector( onTap: onVideoTapped, child: Container( height: videoHeight, width: videoHeight * 3 / 2, decoration: BoxDecoration( color: Colors.grey[300], borderRadius: BorderRadius.circular(4), ), child: const Center( child: Icon( Icons.play_circle_outline, size: 40, color: Colors.white, ), ), ), ) : SizedBox(height: 10,) ], ), ); } ///类型4:一个文本(自适应高度) static Widget createAloneTextItem({ required String text, double verticalPadding = 10, double horizontalPadding = 0, }) { return Padding( padding: EdgeInsets.symmetric( vertical: verticalPadding, horizontal: horizontalPadding, ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ Text( text, style: TextStyle(fontSize: 15, color: Colors.grey), softWrap: true, maxLines: null, // 允许无限行数 ), ], ), ); } /// YesNo static Widget createYesNoSection({ required String title, String yesLabel = '是', String noLabel = '否', required bool? groupValue, required ValueChanged onChanged, double verticalPadding = 15, double horizontalPadding = 10, bool isEdit = true, String text = '', bool isRequired = false, }) { return Padding( padding: EdgeInsets.only( top: 0, right: horizontalPadding, left: horizontalPadding, bottom: verticalPadding, ), child: Container( padding: EdgeInsets.symmetric(horizontal: 10), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(5), ), child: Row( children: [ Expanded( child: Row( children: [ if (isRequired && isEdit) Text('* ', style: TextStyle(color: Colors.red)), Text( title, style: TextStyle( fontSize: 15, fontWeight: FontWeight.bold, color: Colors.black, ), ) ], ), ), if (isEdit) Row( children: [ Row( children: [ Radio( activeColor: Colors.blue, value: true, groupValue: groupValue, onChanged: (val) => onChanged(val!), ), Text(yesLabel), ], ), const SizedBox(width: 16), Row( children: [ Radio( activeColor: Colors.blue, value: false, groupValue: groupValue, onChanged: (val) => onChanged(val!), ), Text(noLabel), ], ), ], ), if (!isEdit) Text(text, style: TextStyle(),) ], ), ), ); } /// 列表标题头(蓝色标识+文字) static Widget createBuildSimpleSection( String title, { double horPadding = 10, }) { return Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), ), child: Padding( padding: EdgeInsets.symmetric(horizontal: horPadding, vertical: 10), child: Row( children: [ Container(width: 3, height: 15, color: Colors.blue), const SizedBox(width: 8), Text( title, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold), ), ], ), ), ); } /// 单纯标题 static Widget headerTitle(String title, {bool isRequired = false}) { return Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), ), child: Row( children: [ if (isRequired) Text('* ', style: TextStyle(color: Colors.red)), Text( title, style: const TextStyle(fontSize: 15, fontWeight: FontWeight.bold), ), ], ), ); } /// 扩展项(根据需求自定义) static Widget createCustomItem({ required Widget child, double verticalPadding = 15, double horizontalPadding = 0, }) { return Padding( padding: EdgeInsets.symmetric( vertical: verticalPadding, horizontal: horizontalPadding, ), child: child, ); } /// 标题加输入框上下排列 static Widget createBuildMultilineInput( String label, String hint, TextEditingController controller, { bool isRequired = false, }) { return Container( height: 130, padding: const EdgeInsets.only(top: 8), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ if (isRequired) Text('* ', style: TextStyle(color: Colors.red)), // 标题 HhTextStyleUtils.mainTitle(label, fontSize: 15), ], ), const SizedBox(height: 8), // 文本输入框,清除默认内边距以与标题左对齐 Expanded( child: TextField( autofocus: false, controller: controller, keyboardType: TextInputType.multiline, maxLines: null, expands: true, style: const TextStyle(fontSize: 15), decoration: InputDecoration( hintText: hint, border: InputBorder.none, contentPadding: isRequired ? EdgeInsets.symmetric(horizontal: 10) : EdgeInsets.zero, // 去除默认内边距 ), ), ), ], ), ); } /// 分类头部 static Widget createYesNoSectionTwo({ required String title, required String yesLabel, required String noLabel, required bool groupValue, required bool canClick, required BuildContext context, required ValueChanged onChanged, double verticalPadding = 15, double horizontalPadding = 10, }) { return Padding( padding: EdgeInsets.only( top: 0, right: horizontalPadding, left: horizontalPadding, bottom: verticalPadding, ), child: Container( padding: EdgeInsets.symmetric(horizontal: 10), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(5), ), child: Row( children: [ Expanded( child: Text( title, style: TextStyle( fontSize: 15, fontWeight: FontWeight.bold, color: Colors.black, ), ), ), Row( children: [ Row( children: [ Radio( activeColor: Colors.blue, value: true, groupValue: groupValue, onChanged: (val) { if (canClick) { onChanged(val!); } else { ToastUtil.showNormal(context, "重大隐患不允许选此项"); } }, // (val) => onChanged(val!), ), Text(yesLabel), ], ), const SizedBox(width: 16), Row( children: [ Radio( activeColor: Colors.blue, value: false, groupValue: groupValue, onChanged: (val) => onChanged(val!), ), Text(noLabel), ], ), ], ), ], ), ), ); } }