flutter_integrated_whb/lib/customWidget/ItemWidgetFactory.dart

512 lines
14 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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: [
Expanded(child: Text(
rightText,
// rightText,
style: TextStyle(fontSize: 15, color: Colors.grey),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),),
SizedBox(width: 2),
Icon(
Icons.arrow_forward_ios_rounded,
color: Colors.black45,
size: 15,
),
],
)
else
Expanded(child: Text(rightText, style: TextStyle(fontSize: 15, color: Colors.grey,),maxLines: 1,
overflow: TextOverflow.ellipsis, textAlign: TextAlign.right,)),
],
),
);
}
// 辅助函数:截断文本
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<String> 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<bool> 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<bool>(
activeColor: Colors.blue,
value: true,
groupValue: groupValue,
onChanged: (val) => onChanged(val!),
),
Text(yesLabel),
],
),
const SizedBox(width: 16),
Row(
children: [
Radio<bool>(
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<bool> 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<bool>(
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<bool>(
activeColor: Colors.blue,
value: false,
groupValue: groupValue,
onChanged: (val) => onChanged(val!),
),
Text(noLabel),
],
),
],
),
],
),
),
);
}
}