option_select_widget.dart 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. import 'package:cached_network_image/cached_network_image.dart';
  2. import 'package:flutter/cupertino.dart';
  3. import 'package:flutter/material.dart';
  4. import 'package:flutter_screenutil/flutter_screenutil.dart';
  5. import 'package:keyboard/data/bean/option_select_item.dart';
  6. import '../../../data/bean/option_select_config.dart';
  7. import '../../../resource/colors.gen.dart';
  8. /// 切换选中时回调
  9. typedef OnOptionSelectCallback =
  10. void Function(OptionSelectConfig config, OptionSelectItem optionItem);
  11. /// 选项选择组件
  12. class OptionSelectWidget extends StatelessWidget {
  13. /// 选项行的配置
  14. final OptionSelectConfig optionSelect;
  15. /// 切换选中时回调
  16. final OnOptionSelectCallback optionSelectCallback;
  17. const OptionSelectWidget({
  18. super.key,
  19. required this.optionSelect,
  20. required this.optionSelectCallback,
  21. });
  22. @override
  23. Widget build(BuildContext context) {
  24. return Column(
  25. crossAxisAlignment: CrossAxisAlignment.start,
  26. children: [
  27. // 标题
  28. _buildTitle(),
  29. SizedBox(height: 8.h),
  30. // 选项
  31. _buildOptionList(),
  32. ],
  33. );
  34. }
  35. /// 图标和标题
  36. Widget _buildTitle() {
  37. String icon = optionSelect.iconUrl;
  38. return Row(
  39. children: [
  40. Visibility(
  41. visible: icon.isNotEmpty,
  42. child: Row(
  43. children: [
  44. // 图标
  45. CachedNetworkImage(
  46. imageUrl: icon,
  47. height: 14.h,
  48. width: 14.w,
  49. fit: BoxFit.fill,
  50. ),
  51. SizedBox(width: 2),
  52. ],
  53. ),
  54. ),
  55. // 标题
  56. Text(
  57. optionSelect.title,
  58. style: TextStyle(
  59. fontSize: 12.sp,
  60. fontWeight: FontWeight.w500,
  61. color: ColorName.black80,
  62. ),
  63. ),
  64. ],
  65. );
  66. }
  67. /// 选项列表
  68. Widget _buildOptionList() {
  69. return Wrap(
  70. direction: Axis.horizontal,
  71. alignment: WrapAlignment.start,
  72. // 主轴间距
  73. spacing: 8.0,
  74. // 交叉轴间距
  75. runSpacing: 7.0,
  76. children: [
  77. for (var option in optionSelect.options)
  78. _buildOptionItem(optionSelect, option),
  79. ],
  80. );
  81. }
  82. /// 选项
  83. /// [rowConfig] 选项行的配置
  84. /// [optionItem] 当前构建的那一项
  85. Widget _buildOptionItem(
  86. OptionSelectConfig rowConfig,
  87. OptionSelectItem optionItem,
  88. ) {
  89. // 背景圆角
  90. double bgBorderRadius = 31.r;
  91. // 背景,选中时为渐变色,未选中时为灰色
  92. BoxDecoration bgDecoration;
  93. if (optionItem.selected) {
  94. bgDecoration = BoxDecoration(
  95. gradient: LinearGradient(
  96. colors: [
  97. ColorName.bgOptionSelectSelected1,
  98. ColorName.bgOptionSelectSelected2,
  99. ],
  100. begin: Alignment.centerLeft,
  101. end: Alignment.centerRight,
  102. ),
  103. borderRadius: BorderRadius.circular(bgBorderRadius),
  104. );
  105. } else {
  106. bgDecoration = BoxDecoration(
  107. color: ColorName.bgOptionSelectNormal,
  108. borderRadius: BorderRadius.circular(bgBorderRadius),
  109. );
  110. }
  111. return GestureDetector(
  112. onTap: () {
  113. optionSelectCallback(rowConfig, optionItem);
  114. },
  115. child: Container(
  116. padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 6.h),
  117. decoration: bgDecoration,
  118. child: Text(
  119. optionItem.name,
  120. style: TextStyle(
  121. fontSize: 13.sp,
  122. fontWeight: FontWeight.w400,
  123. // 文字颜色,选中时为白色,未选中时为黑色
  124. color: optionItem.selected ? ColorName.white : ColorName.black80,
  125. ),
  126. ),
  127. ),
  128. );
  129. }
  130. }