step_card.dart 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. import 'package:flutter/cupertino.dart';
  2. import 'package:flutter_screenutil/flutter_screenutil.dart';
  3. import '../../../data/bean/widget_location.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 Widget? topTitleWidget;
  13. /// 顶部图标组件
  14. final Image? topIconWidget;
  15. /// 内容组件
  16. final Widget contentWidget;
  17. /// 顶部图标组件的位置信息
  18. final WidgetLocation? topIconWidgetLocation;
  19. const StepCard({
  20. super.key,
  21. required this.bgImageProvider,
  22. this.topTitleWidget,
  23. required this.contentWidget,
  24. this.topIconWidget,
  25. this.topIconWidgetLocation,
  26. });
  27. @override
  28. Widget build(BuildContext context) {
  29. var topIconWidgetLocation =
  30. this.topIconWidgetLocation ?? WidgetLocation(null, -11.h, 0, null);
  31. return Container(
  32. margin: EdgeInsets.only(left: 12.w, top: 10.h, right: 12.w),
  33. child: Stack(
  34. // 不裁切超出区域的子组件,例如下面的顶部的图标
  35. clipBehavior: Clip.none,
  36. children: [
  37. // 顶部的图标
  38. topIconWidget == null
  39. ? SizedBox()
  40. : Positioned(
  41. left: topIconWidgetLocation.left,
  42. top: topIconWidgetLocation.top,
  43. right: topIconWidgetLocation.right,
  44. bottom: topIconWidgetLocation.bottom,
  45. child: topIconWidget!,
  46. ),
  47. // 卡片背景
  48. Container(
  49. // 渐变背景
  50. // decoration: BoxDecoration(
  51. // gradient: LinearGradient(
  52. // colors: [Color(0xFFEFE9FF), Color(0xFFFBFAFF)],
  53. // begin: Alignment.topCenter,
  54. // end: Alignment.bottomRight,
  55. // ),
  56. // shape: BoxShape.rectangle,
  57. // border: Border.all(color: ColorName.white80, width: 1.w),
  58. // borderRadius: BorderRadius.all(Radius.circular(20.r)),
  59. // ),
  60. // 卡片背景
  61. decoration: BoxDecoration(
  62. image: DecorationImage(image: bgImageProvider, fit: BoxFit.fill),
  63. ),
  64. constraints: BoxConstraints(
  65. minHeight: 260.h
  66. ),
  67. child: Column(
  68. // 左对齐
  69. crossAxisAlignment: CrossAxisAlignment.start,
  70. children: [
  71. // 顶部标题区域
  72. topTitleWidget != null ? topTitleWidget! : SizedBox(),
  73. // 内容区域
  74. contentWidget,
  75. SizedBox(height: 12.h),
  76. ],
  77. ),
  78. ),
  79. ],
  80. ),
  81. );
  82. }
  83. }
  84. /// 步骤标题组件
  85. class StepTitleWidget extends StatelessWidget {
  86. /// 步骤标签
  87. final String stepLabel;
  88. /// 步骤标题
  89. final String stepTitle;
  90. /// 步骤描述
  91. final String stepDesc;
  92. const StepTitleWidget({
  93. super.key,
  94. this.stepLabel = "",
  95. this.stepTitle = "",
  96. this.stepDesc = "",
  97. });
  98. @override
  99. Widget build(BuildContext context) {
  100. return Column(
  101. children: [
  102. // 步骤标题
  103. Container(
  104. margin: EdgeInsets.only(top: 16.h, bottom: 4.h),
  105. child: _buildStepTitle(),
  106. ),
  107. // 步骤描述
  108. stepDesc.isNotEmpty ? _buildStepDesc(stepDesc) : SizedBox(height: 6.h),
  109. ],
  110. );
  111. }
  112. /// 步骤标题
  113. Widget _buildStepTitle() {
  114. return Container(
  115. padding: EdgeInsets.only(left: 12.w),
  116. child: Row(
  117. children: [
  118. // 步骤标签
  119. Visibility(
  120. visible: stepLabel.isNotEmpty,
  121. child: Container(
  122. margin: EdgeInsets.only(right: 10.w),
  123. child: StepLabelWidget(label: stepLabel),
  124. ),
  125. ),
  126. // 标题
  127. GradientText(
  128. // 渐变颜色
  129. colors: [ColorName.stepTitleColor1, ColorName.stepTitleColor2],
  130. child: Text(
  131. stepTitle,
  132. style: TextStyle(fontSize: 20.sp, fontWeight: FontWeight.w700),
  133. ),
  134. ),
  135. ],
  136. ),
  137. );
  138. }
  139. /// 构建步骤描述
  140. Widget _buildStepDesc(String desc) {
  141. if (desc.isEmpty) {
  142. return SizedBox();
  143. }
  144. return Row(
  145. children: [
  146. Expanded(
  147. child: Container(
  148. margin: EdgeInsets.only(left: 12.w, right: 12.w),
  149. child: Text(
  150. desc,
  151. // 超过时显示省略号
  152. overflow: TextOverflow.ellipsis,
  153. // 最多多少行
  154. maxLines: 1,
  155. style: TextStyle(
  156. fontSize: 12.sp,
  157. fontWeight: FontWeight.w400,
  158. color: ColorName.black60,
  159. ),
  160. ),
  161. ),
  162. ),
  163. SizedBox(height: 16.h),
  164. ],
  165. );
  166. }
  167. }