step_card.dart 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. import 'package:flutter/cupertino.dart';
  2. import 'package:flutter_screenutil/flutter_screenutil.dart';
  3. import 'package:get/get.dart';
  4. import '../../../resource/colors.gen.dart';
  5. import '../../../widget/gradient_text.dart';
  6. import '../intimacy_analyse_upload/widget/step_label_widget.dart';
  7. /// 步骤卡片,支持设置卡片背景、步骤标题、步骤描述、顶部图标和内容区域
  8. class StepCard extends StatelessWidget {
  9. /// 卡片背景
  10. final ImageProvider bgImageProvider;
  11. /// 步骤标签
  12. final String? stepLabel;
  13. /// 步骤标题
  14. final String stepTitle;
  15. /// 步骤描述
  16. final String stepDesc;
  17. /// 顶部图标
  18. final Image? topIconWidget;
  19. /// 内容组件
  20. final Widget contentWidget;
  21. const StepCard({
  22. super.key,
  23. required this.bgImageProvider,
  24. required this.stepLabel,
  25. required this.stepTitle,
  26. required this.stepDesc,
  27. required this.contentWidget,
  28. this.topIconWidget,
  29. });
  30. @override
  31. Widget build(BuildContext context) {
  32. return Container(
  33. margin: EdgeInsets.only(left: 12.w, top: 10.h, right: 12.w),
  34. child: Stack(
  35. // 不裁切超出区域的子组件,例如下面的顶部的图标
  36. clipBehavior: Clip.none,
  37. children: [
  38. // 顶部的图标
  39. topIconWidget == null
  40. ? SizedBox()
  41. : Positioned(top: -11.h, right: 0, child: topIconWidget!),
  42. // 卡片背景
  43. Container(
  44. decoration: BoxDecoration(
  45. image: DecorationImage(image: bgImageProvider, fit: BoxFit.fill),
  46. ),
  47. child: Column(
  48. // 左对齐
  49. crossAxisAlignment: CrossAxisAlignment.start,
  50. children: [
  51. // 步骤标题
  52. Container(
  53. margin: EdgeInsets.only(
  54. // 存在步骤标签时,才有左边距
  55. left: hasStepLabel() ? 12.w : 0,
  56. top: 16.h,
  57. ),
  58. child: _buildStepTitle(),
  59. ),
  60. SizedBox(height: 4.h),
  61. // 步骤描述
  62. stepDesc.isNotEmpty
  63. ? _buildStepDesc(stepDesc)
  64. : SizedBox(height: 6.h),
  65. // 内容区域
  66. contentWidget,
  67. SizedBox(height: 12.h),
  68. ],
  69. ),
  70. ),
  71. ],
  72. ),
  73. );
  74. }
  75. /// 是否有步骤标签
  76. bool hasStepLabel() {
  77. String stepLabelStr = stepLabel ?? "";
  78. return stepLabelStr.isNotEmpty == true;
  79. }
  80. /// 步骤标题
  81. Widget _buildStepTitle() {
  82. // 步骤标签
  83. Widget stepLabelWidget;
  84. if (hasStepLabel()) {
  85. stepLabelWidget = StepLabelWidget(label: stepLabel ?? "");
  86. } else {
  87. stepLabelWidget = SizedBox();
  88. }
  89. return Row(
  90. children: [
  91. // 步骤标签
  92. stepLabelWidget,
  93. SizedBox(width: 10.w),
  94. // 标题
  95. GradientText(
  96. // 渐变颜色
  97. colors: [ColorName.stepTitleColor1, ColorName.stepTitleColor2],
  98. child: Text(
  99. stepTitle,
  100. style: TextStyle(fontSize: 20.sp, fontWeight: FontWeight.w700),
  101. ),
  102. ),
  103. ],
  104. );
  105. }
  106. /// 构建步骤描述
  107. Widget _buildStepDesc(String desc) {
  108. if (desc.isEmpty) {
  109. return SizedBox();
  110. }
  111. return Row(
  112. children: [
  113. Expanded(
  114. child: Container(
  115. margin: EdgeInsets.only(left: 12.w, right: 12.w),
  116. child: Text(
  117. desc,
  118. // 超过时显示省略号
  119. overflow: TextOverflow.ellipsis,
  120. // 最多多少行
  121. maxLines: 2,
  122. style: TextStyle(
  123. fontSize: 12.sp,
  124. fontWeight: FontWeight.w400,
  125. color: ColorName.black60,
  126. ),
  127. ),
  128. ),
  129. ),
  130. SizedBox(height: 16.h),
  131. ],
  132. );
  133. }
  134. }