156 lines
4.4 KiB
Dart
156 lines
4.4 KiB
Dart
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: Column(
|
|
children: _buildDetailRows(),
|
|
),
|
|
),
|
|
|
|
// — 底部标签区 —
|
|
if (showBottomTags && bottomTags.isNotEmpty)
|
|
Padding(
|
|
padding: const EdgeInsets.only(left: 15, right: 15, bottom: 15),
|
|
child: Wrap(spacing: 5, runSpacing: 5, children: bottomTags),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
// 构建详情行
|
|
List<Widget> _buildDetailRows() {
|
|
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] : '';
|
|
|
|
rows.add(
|
|
Padding(
|
|
padding: const EdgeInsets.only(bottom: 8),
|
|
child: _DetailRow(left: left, right: right),
|
|
),
|
|
);
|
|
}
|
|
return rows;
|
|
}
|
|
}
|
|
|
|
/// 详情行组件:固定左右布局,平均分配宽度,各自换行
|
|
/// 如果只有左侧文本,则靠左显示
|
|
class _DetailRow extends StatelessWidget {
|
|
final String left;
|
|
final String right;
|
|
|
|
const _DetailRow({
|
|
Key? key,
|
|
required this.left,
|
|
required this.right,
|
|
}) : super(key: key);
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
// 如果右侧文本为空,只显示左侧文本,靠左显示
|
|
if (right.isEmpty) {
|
|
return Align(
|
|
alignment: Alignment.centerLeft,
|
|
child: _DetailText(left, textAlign: TextAlign.left),
|
|
);
|
|
}
|
|
|
|
return Row(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// 左侧文本 - 占50%宽度
|
|
Expanded(
|
|
flex: 1,
|
|
child: _DetailText(left, textAlign: TextAlign.left),
|
|
),
|
|
|
|
// 中间间距
|
|
const SizedBox(width: 10),
|
|
|
|
// 右侧文本 - 占50%宽度
|
|
Expanded(
|
|
flex: 1,
|
|
child: _DetailText(right, textAlign: TextAlign.right),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Detail 文本封装:支持自动换行和指定的对齐方式
|
|
class _DetailText extends StatelessWidget {
|
|
final String text;
|
|
final TextAlign textAlign;
|
|
|
|
const _DetailText(this.text, {
|
|
Key? key,
|
|
required this.textAlign,
|
|
}) : super(key: key);
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Text(
|
|
text,
|
|
style: HhTextStyleUtils.secondaryTitleStyle,
|
|
softWrap: true, // 允许换行
|
|
textAlign: textAlign, // 使用指定的对齐方式
|
|
);
|
|
}
|
|
} |