You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

185 lines
5.7KB

  1. import 'package:flutter/material.dart';
  2. import 'package:flutter_svg/flutter_svg.dart';
  3. import 'package:get/get.dart';
  4. import '../../../themes/app_dimension.dart';
  5. import '../../../models/item_dropdown.dart';
  6. import '../../../themes/app_colors.dart';
  7. import '../../../themes/styles_text.dart';
  8. import '../../../utils/app_images.dart';
  9. import '../../../utils/validators.dart';
  10. class DropdownBottomSheet extends StatefulWidget {
  11. final String? initValue;
  12. final List<ItemDropDown> dataSources;
  13. final Function(ItemDropDown) onSelected;
  14. final Color? borderColor;
  15. final String hint;
  16. final double? height;
  17. final String? errorText;
  18. final bool isDisable;
  19. final EdgeInsetsGeometry? contentPadding;
  20. final Color? disabledColor;
  21. const DropdownBottomSheet({
  22. Key? key,
  23. required this.dataSources,
  24. required this.onSelected,
  25. required this.hint,
  26. this.initValue,
  27. this.borderColor,
  28. this.height,
  29. this.errorText,
  30. this.isDisable = false,
  31. this.contentPadding,
  32. this.disabledColor,
  33. }) : super(key: key);
  34. @override
  35. _DropdownBottomSheetState createState() => _DropdownBottomSheetState();
  36. }
  37. class _DropdownBottomSheetState extends State<DropdownBottomSheet> {
  38. var dataSources = ValueNotifier(<ItemDropDown>[]);
  39. var selectValue = ValueNotifier(ItemDropDown());
  40. int _selectedIndex = 0;
  41. FixedExtentScrollController? scrollController;
  42. final _searchCtl = TextEditingController();
  43. @override
  44. void initState() {
  45. super.initState();
  46. }
  47. @override
  48. void dispose() {
  49. _searchCtl.dispose();
  50. super.dispose();
  51. }
  52. @override
  53. Widget build(BuildContext context) {
  54. _selectedIndex = widget.dataSources.indexWhere((element) {
  55. return element.key == widget.initValue;
  56. });
  57. if (_selectedIndex >= 0) {
  58. selectValue.value = widget.dataSources[_selectedIndex];
  59. } else {
  60. selectValue.value = ItemDropDown(key: '', value: '');
  61. }
  62. return InkWell(
  63. onTap: () {
  64. FocusScope.of(context).requestFocus(FocusNode());
  65. widget.isDisable ? null : _modalBottomSheetMenu();
  66. },
  67. child: Column(
  68. crossAxisAlignment: CrossAxisAlignment.start,
  69. children: [
  70. Container(
  71. padding: widget.contentPadding ??
  72. EdgeInsets.symmetric(
  73. horizontal: 12.w,
  74. vertical: 16.h,
  75. ),
  76. decoration: BoxDecoration(
  77. color: widget.isDisable ? (widget.disabledColor ?? AppColors.background1) : AppColors.white,
  78. borderRadius: BorderRadius.circular(12),
  79. border: Border.all(
  80. color: AppColors.neutral4,
  81. width: 1,
  82. ),
  83. ),
  84. child: Row(
  85. children: [
  86. Expanded(
  87. child: ValueListenableBuilder<ItemDropDown>(
  88. valueListenable: selectValue,
  89. builder: (context, selected, _) {
  90. if (Validators.stringNotNullOrEmpty(selected.key)) {
  91. return Text(
  92. selected.value ?? '',
  93. style: StylesText.body6,
  94. maxLines: 1,
  95. );
  96. } else {
  97. return Text(
  98. widget.hint,
  99. style: StylesText.body6.copyWith(
  100. color: AppColors.neutral3,
  101. ),
  102. );
  103. }
  104. },
  105. ),
  106. ),
  107. SvgPicture.asset(AssetSVG.icArrowDown),
  108. ],
  109. ),
  110. ),
  111. if (widget.errorText != null) ...[
  112. SizedBox(
  113. height: 4.h,
  114. ),
  115. Text(
  116. widget.errorText ?? '',
  117. style: StylesText.caption1.copyWith(
  118. color: AppColors.semantic2,
  119. ),
  120. )
  121. ],
  122. ],
  123. ),
  124. );
  125. }
  126. void _modalBottomSheetMenu() {
  127. _searchCtl.clear();
  128. dataSources.value = List.of(widget.dataSources);
  129. showDialog(
  130. context: context,
  131. builder: (context) {
  132. return AlertDialog(
  133. contentPadding: const EdgeInsets.all(8),
  134. content: Container(
  135. width: double.maxFinite,
  136. child: Column(
  137. mainAxisSize: MainAxisSize.min,
  138. children: <Widget>[
  139. Expanded(
  140. child: ValueListenableBuilder<List<ItemDropDown>>(
  141. valueListenable: dataSources,
  142. builder: (context, sources, _) {
  143. return ListView.builder(
  144. shrinkWrap: true,
  145. itemBuilder: ((context, index) {
  146. var item = sources[index];
  147. return InkWell(
  148. onTap: () {},
  149. child: RadioListTile<ItemDropDown>(
  150. value: item,
  151. title: Text(
  152. item.value ?? '',
  153. style: StylesText.body6,
  154. ),
  155. groupValue: item.key == selectValue.value.key ? item : null,
  156. onChanged: (val) {
  157. Get.back();
  158. widget.onSelected(val!);
  159. },
  160. ),
  161. );
  162. }),
  163. itemCount: sources.length,
  164. );
  165. },
  166. ),
  167. )
  168. ],
  169. ),
  170. ),
  171. );
  172. },
  173. );
  174. }
  175. }