step_card.dart 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  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. child: Column(
  65. // 左对齐
  66. crossAxisAlignment: CrossAxisAlignment.start,
  67. children: [
  68. // 顶部标题区域
  69. topTitleWidget != null ? topTitleWidget! : SizedBox(),
  70. // 内容区域
  71. contentWidget,
  72. SizedBox(height: 12.h),
  73. ],
  74. ),
  75. ),
  76. ],
  77. ),
  78. );
  79. }
  80. }
  81. /// 步骤标题组件
  82. class StepTitleWidget extends StatelessWidget {
  83. /// 步骤标签
  84. final String stepLabel;
  85. /// 步骤标题
  86. final String stepTitle;
  87. /// 步骤描述
  88. final String stepDesc;
  89. const StepTitleWidget({
  90. super.key,
  91. this.stepLabel = "",
  92. this.stepTitle = "",
  93. this.stepDesc = "",
  94. });
  95. @override
  96. Widget build(BuildContext context) {
  97. return Column(
  98. children: [
  99. // 步骤标题
  100. Container(
  101. margin: EdgeInsets.only(top: 16.h, bottom: 4.h),
  102. child: _buildStepTitle(),
  103. ),
  104. // 步骤描述
  105. stepDesc.isNotEmpty ? _buildStepDesc(stepDesc) : SizedBox(height: 6.h),
  106. ],
  107. );
  108. }
  109. /// 步骤标题
  110. Widget _buildStepTitle() {
  111. return Container(
  112. padding: EdgeInsets.only(left: 12.w),
  113. child: Row(
  114. children: [
  115. // 步骤标签
  116. Visibility(
  117. visible: stepLabel.isNotEmpty,
  118. child: Container(
  119. margin: EdgeInsets.only(right: 10.w),
  120. child: StepLabelWidget(label: stepLabel),
  121. ),
  122. ),
  123. // 标题
  124. GradientText(
  125. // 渐变颜色
  126. colors: [ColorName.stepTitleColor1, ColorName.stepTitleColor2],
  127. child: Text(
  128. stepTitle,
  129. style: TextStyle(fontSize: 20.sp, fontWeight: FontWeight.w700),
  130. ),
  131. ),
  132. ],
  133. ),
  134. );
  135. }
  136. /// 构建步骤描述
  137. Widget _buildStepDesc(String desc) {
  138. if (desc.isEmpty) {
  139. return SizedBox();
  140. }
  141. return Row(
  142. children: [
  143. Expanded(
  144. child: Container(
  145. margin: EdgeInsets.only(left: 12.w, right: 12.w),
  146. child: Text(
  147. desc,
  148. // 超过时显示省略号
  149. overflow: TextOverflow.ellipsis,
  150. // 最多多少行
  151. maxLines: 1,
  152. style: TextStyle(
  153. fontSize: 12.sp,
  154. fontWeight: FontWeight.w400,
  155. color: ColorName.black60,
  156. ),
  157. ),
  158. ),
  159. ),
  160. SizedBox(height: 16.h),
  161. ],
  162. );
  163. }
  164. }