qhd-prevention-flutter/lib/customWidget/danner_repain_item.dart

148 lines
5.3 KiB
Dart
Raw Normal View History

2025-07-07 16:49:05 +08:00
import 'package:flutter/material.dart';
import '../tools/tools.dart';
/// 通用列表卡片组件:
/// - 两两为一组,优先尝试同一行显示左右两列并左/右对齐;
/// - 如放不下,则自动拆成两行,上行左对齐,下行右对齐。
class DannerRepainItem extends StatelessWidget {
final String title;
final List<String> details;
final bool showBottomTags;
final List<Widget> bottomTags;
final bool showTitleIcon;
const DannerRepainItem({
Key? key,
required this.title,
required this.details,
this.showBottomTags = false,
this.showTitleIcon = true,
this.bottomTags = const [],
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(left: 15, right: 15, bottom: 15),
child: Container(
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(5)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// — 标题行 —
Padding(
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 15),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(children: [
if (showTitleIcon)
const Icon(Icons.star_rate_sharp, color: Colors.green, size: 18),
SizedBox(width: showTitleIcon ? 5 : 0),
Text(title, style: const TextStyle(fontSize: 14)),
]),
const Icon(Icons.arrow_forward_ios_rounded, color: Colors.grey, size: 15),
],
),
),
const Divider(height: 1),
// — 详情区:动态两列/换行 —
Padding(
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 15),
child: LayoutBuilder(builder: (context, constraints) {
// 间距:你可以根据设计随意调整
const double horizontalGap = 20;
const double verticalGap = 5;
List<Widget> rows = [];
for (int i = 0; i < details.length; i += 2) {
final left = details[i];
final right = (i + 1 < details.length) ? details[i + 1] : '';
// 测量文字宽度
final leftPainter = TextPainter(
text: TextSpan(text: left, style: HhTextStyleUtils.secondaryTitleStyle),
maxLines: 1,
textDirection: TextDirection.ltr,
)..layout();
final rightPainter = TextPainter(
text: TextSpan(text: right, style: HhTextStyleUtils.secondaryTitleStyle),
maxLines: 1,
textDirection: TextDirection.ltr,
)..layout();
final canFitOneLine = right.isNotEmpty &&
(leftPainter.width + horizontalGap + rightPainter.width)
<= constraints.maxWidth;
if (right.isNotEmpty && canFitOneLine) {
// 同行显示,左右对齐
rows.add(Padding(
padding: EdgeInsets.only(bottom: verticalGap),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_DetailText(left),
_DetailText(right),
],
),
));
} else {
// 拆为两行
rows.add(Padding(
padding: EdgeInsets.only(bottom: verticalGap),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// 上行:左对齐
_DetailText(left),
if (right.isNotEmpty)
// 下行:右对齐
Align(
alignment: Alignment.centerRight,
child: _DetailText(right),
),
],
),
));
}
}
return Column(children: rows);
}),
),
// — 底部标签区 —
if (showBottomTags && bottomTags.isNotEmpty)
Padding(
padding: const EdgeInsets.only(left: 15, right: 15, bottom: 15),
child: Wrap(spacing: 5, runSpacing: 5, children: bottomTags),
),
],
),
),
);
}
}
/// Detail 文本封装:
/// 默认一行不换行;若超出则让整个组件撑宽,由外层判断拆行。
class _DetailText extends StatelessWidget {
final String text;
const _DetailText(this.text, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Text(
text,
style: HhTextStyleUtils.secondaryTitleStyle,
softWrap: false,
overflow: TextOverflow.visible,
);
}
}