import 'package:flutter/material.dart'; import '../tools/tools.dart'; /// 通用列表卡片组件: /// - 两两为一组,优先尝试同一行显示左右两列并左/右对齐; /// - 如放不下,则自动拆成两行,上行左对齐,下行右对齐。 class DannerRepainItem extends StatelessWidget { final String title; final List details; final bool showBottomTags; final List 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 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, ); } }